Afnetworking 3.0 Migration: How to Post with Headers and Http Body

afnetworking 3.0 Migration: how to POST with headers and HTTP Body

I was able to figure this out myself.

Here's the solution.

First, you need to create the NSMutableURLRequest from AFJSONRequestSerializer first where you can set the method type to POST.

On this request, you get to setHTTPBody after you have set your HTTPHeaderFields. Make sure to set the body after you have set the Header fields for content-type, or else the api will give a 400 error.

Then on the manager create a dataTaskWithRequest using the above NSMutableURLRequest. Don't forget to resume the dataTask at the very end or else nothing will get sent yet. Here's my solution code, hopefully someone gets to use this successfully:

NSDictionary *body = @{@"snippet": @{@"topLevelComment":@{@"snippet":@{@"textOriginal":self.commentToPost.text}},@"videoId":self.videoIdPostingOn}};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

NSMutableURLRequest *req = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:[NSString stringWithFormat:@"https://www.googleapis.com/youtube/v3/commentThreads?part=snippet&access_token=%@",[[LoginSingleton sharedInstance] getaccesstoken]] parameters:nil error:nil];

req.timeoutInterval= [[[NSUserDefaults standardUserDefaults] valueForKey:@"timeoutInterval"] longValue];
[req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[req setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[req setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];


[[manager dataTaskWithRequest:req completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

if (!error) {
NSLog(@"Reply JSON: %@", responseObject);

if ([responseObject isKindOfClass:[NSDictionary class]]) {
//blah blah
}
} else {
NSLog(@"Error: %@, %@, %@", error, response, responseObject);
}
}] resume];

send POST request with body dictionary in afnetworking 3.0

From AFNetworking's GitHub:

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id formData) {
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];

//Set the request body here

} error:nil];

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];

NSURLSessionUploadTask *uploadTask;
uploadTask = [manager
uploadTaskWithStreamedRequest:request
progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
dispatch_async(dispatch_get_main_queue(), ^{
//Update the progress view
[progressView setProgress:uploadProgress.fractionCompleted];
});
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"%@ %@", response, responseObject);
}
}];

[uploadTask resume];

Edit

The above answer is useful especially if you want to set a custom request body.

If you only need to POST a simple set of parameters you can do it like this:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];

[manager POST:@"http://exaple.com/path" parameters:@{@"param1" : @"foo", @"anotherParameter" : @"bar"} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

//success block

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

//failure block

}];

Use custom HTTP Headers with AFNetworking 3.0

Ok I found the answer, nothing actually changed, but it's not obvious, here's the code:

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let manager = AFURLSessionManager(sessionConfiguration: configuration)

let request = NSMutableURLRequest(URL: remoteFileURL!)
request.setValue("", forHTTPHeaderField: "If-None-Match")
let downloadTask = manager.downloadTaskWithRequest(request, progress: nil, destination: { (targetURL: NSURL, response: NSURLResponse) -> NSURL in
// Success
}, completionHandler: { (response: NSURLResponse, filePath: NSURL?, error: NSError?) -> Void in
// Error
})
downloadTask.resume()

Migrating from AFNetworking 2.5.4 to 3.1

As you can see in the README AFNetworking has switched to NSURLSession. This means that to create a request you do something like this:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];

Your exact function can't be replicated but you can probably work your way back to the caller of that function and replace it with something similar.



Related Topics



Leave a reply



Submit