Recently, I have found time to look into AFNetworking a bit more and it is also time to change to another networking library as it would be most unwise to keep using a library that has ceased to be developed since mid 2011. ASIHTTPRequest still seems to work fine for the occasional, light networking uses that I need it for.
AFNetworking turns out to be much simpler than I had initially expected. It is also much more powerful, flexible and maintainable going forward. The main reason for this is that it is built on top of NSURLConnection and NSOperation, and it uses blocks which is also the reason that it looks much more complex when I first looked at it (at which time my understanding of blocks is next to nil and hardly know anything about NSURLConnection or NSOperation).
AFNetworking has good documentation, but there there seems very little example around. And I prefer to learn by going through an example, especially short codes that illustrate the basic principle or approach. In particular, I was puzzled by how to make a simple HTTP GET or POST request using AFNetworking. Here are some simple codes snippet and notes.
Set Up your Project to Use AFNetworking
The Getting Started guide on AFNetworking github page is most useful for this purpose.
HTTP GET Request
You need to use the AFHTTPClient and AFHTTPRequestOperation, so import them as follows :
#import "AFHTTPClient.h"
#import "AFHTTPRequestOperation.h"
The codes:
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://yourServerAddress.com/"]];
[httpClient setParameterEncoding:AFFormURLParameterEncoding];
NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
path:@"http://yourServerAddress.com/example?name=foo"
parameters:nil];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
AFHTTPRequestOperation *operation = [httpClient HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject) {
//-- This block gets invoked when the operation is successful
//-- Here it simply print out the responseObject as text in the log
NSLog(@"Response: %@", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//-- This block gets invoked when the operation fails
NSLog(@"Error: %@", error.localizedDescription);
}];
//-- The following codes allow you to track the download progress (if required)
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
//-- This block gets invoked periodically as the download progress
NSLog(@"bytesRead: %i; totalBytesRead: %lld; totalexpected: %lld", bytesRead, totalBytesRead, totalBytesExpectedToRead);
}];
//-- end of the download progress tracking code
[httpClient enqueueHTTPRequestOperation:operation];
Alternative codes:
(using the getPath: method in AFHTTPClient)
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://yourServerAddress.com/"]];
NSString *pathStr = @"/example?name=foo";
[httpClient getPath:pathStr parameters:paramaters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(@"Request Successful, response '%@'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error.localizedDescription);
}];
The alternative is shorter, but the first version is more customisable. In particular, it allows you to get a reference to the relevant AFHTTPRequestOperation.
HTTP POST Request
Likewise, you need to use the AFHTTPClient and AFHTTPRequestOperation, so import them as noted above.
The codes:
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://yourServerAddress.com/"]];
//-- the content of the POST request is passed in as an NSDictionary
//-- in this example, there are two keys with an object each
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:
object1, @"KEY_NAME_1",
object2, @"KEY_NAME_2",
nil];
[httpClient postPath:@"/postExample/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(@"Request Successful, response '%@'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error.localizedDescription);
}];
Subclassing AFHTTPClient
The above codes use an instance of the AFHTTPClient class. The documentation for AFNetworking, however, suggests that we should sub-class it for each website or web application that the app communicates with.