-
Notifications
You must be signed in to change notification settings - Fork 0
Introduction to AFNetworking
AFNetworking is Gowalla's open-source networking library for iOS and Mac OS X. It's built on top of familiar Foundation network classes, using NSOperation
for scheduling and concurrency, and blocks for convenience and flexibility.
What follows is an overview of the design principles and guiding ideas behind AFNetworking. After reading this, you should have a solid understanding of how you can integrate it into your project.
At the core of AFNetworking is AFURLConnectionOperation
, whose sole purpose is to make asynchronous network requests. Each operation manages a single request from start to finish.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com"]];
AFURLConnectionOperation *operation = [[[AFURLConnectionOperation alloc] initWithRequest:request] autorelease];
As the name implies, AFURLConnectionOperation
communicates over an NSURLConnection
. Also implied by its name, AFURLConnectionOperation
is a subclass of NSOperation
. In combination, we get something that can execute concurrently with other network operations, and--if the need arises--be cancelled at a moment's notice.
Streaming with AFURLConnection
is as easy as hooking up an NSInputStream
and / or NSOutputStream
, and tracking the progress of a file upload or download is just a matter of setting a callback block. Otherwise, you can simply get all of the response data when the operation finishes, with setCompletionBlock:
.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/encode"]];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
operation.inputStream = [NSInputStream inputStreamWithFileAtPath:[[NSBundle mainBundle] pathForResource:@"large-image" ofType:@"tiff"]];
operation.outputStream = [NSOutputStream outputStreamToMemory];
Because of its self-contained, single-purpose design, you could very well stop at AFURLConnectionOperation
and stick to the bare metal, so to speak. But if your app downloads images, or reads JSON or XML from a web API, AFNetworking has much more to offer.
One step up from AFURLConnectionOperation
is AFHTTPRequestOperation
, which is specifically geared towards communicating over HTTP and HTTPS. AFHTTPRequestOperation
creates a distinction between successful and unsuccessful requests — where success and failure are determined by the HTTP status code and whether the MIME type of the response is deemed acceptable.
But what's most significant about AFHTTPRequestOperation
are the subclasses built on top of it: AFJSONRequestOperation
, AFXMLRequestOperation
, AFPropertyListRequestOperation
, and AFImageRequestOperation
. Each of these subclasses caters to particular types of content, so network operations return JSON objects or images rather than raw NSData
.
For example, AFJSONRequestOperation
provides the class method JSONRequestOperationWithRequest:success:failure
. The returned operation automatically checks for a JSON MIME type and a status code in the 2XX range; if those check out, it returns a JSON object parsed from the response data in a callback block.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://gowalla.com/users/mattt.json"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(@"Name: %@ %@", [JSON valueForKeyPath:@"first_name"], [JSON valueForKeyPath:@"last_name"]);
} failure:nil];
JSON (NSJSONSerializer
when available and falling back to JSONKit), XML (using NSXMLParser
, or NSXMLDocument
on OS X), Plist (deserializing directly into Foundation objects), and images (with UIImage
or NSImage
)--AFNetworking includes support for all of these out of the box, so you're ready for pretty much anything the web can throw at you.
While we're on the subject of the web, let's talk about a typical iOS or Mac application. If it's doing any networking at all, it's likely acting as a frontend for a particular API, or perhaps even several.
Enter AFHTTPClient
.
AFHTTPClient
encapsulates the details of talking to a single API: a base URL, authentication credentials, and HTTP headers. Using this information, AFHTTPClient
constructs NSMutableURLRequest
objects that can be used in any manner of AFHTTPRequestOperation
.
[[AFGowallaAPIClient sharedClient] getPath:@"/spots/9223" parameters:nil success:^(id response) {
NSLog(@"Name: %@", [response valueForKeyPath:@"name"]);
NSLog(@"Address: %@", [response valueForKeyPath:@"address.street_address"]);
} failure:nil];
AFHTTPClient
can even automatically detect the correct kind of operation to use for a particular request. For example, a request with a .json
extension would use AFJSONRequestOperation
, whereas a request with the Accept
header set to application/xml
would use AFXMLRequestOperation
. (See the AFHTTPClientOperation
protocol for more details.)
Magic isn't for everyone all of the time. In the above case, if you wanted to force a particular operation, all you would need to do is override AFHTTPClient -requestWithMethod:path:parameters:
--and poof, like magic… the magic is gone!
The final piece of AFNetworking has to do with image loading. You met AFImageRequestOperation
earlier, along with its AFHTTPRequestOperation
brethren, but that was only part of the larger picture.
On iOS, AFNetworking adds category methods on UIImageView
that make asynchronous image loading ridiculously easy. Observe:
[imageView setImageWithURL:imageURL];
Not only is that easy--it's unbelievably fast. On a decent WiFi connection, table view cell images will load as fast as you scroll!
AFImageRequestOperation
can even make a 3G or EDGE connection feel downright snappy. Remember that part about being able to cancel an AFURLConnectionOperation
? This turns out to be especially useful for image loading. As table view cells are recycled, for instance, setting a new image URL will automatically cancel the previous request.
Thus concludes our whirlwind tour of AFNetworking. We hope you've been emboldened and inspired to give it a try in your own project.
Looking for a place to start? Check out the README for some really useful code samples. AFNetworking also has some great documentation (if I don't say so myself)
If you'd like to contribute to AFNetworking, we would most certainly appreciate the help. Open an issue on GitHub, or if you feel so inclined, create a patch and submit a pull request. Also, if you are fluent in a language other than English, we'd love to make translations of the documentation available.