Introduction to AFNetworking

AFNetwork logo

AFNetworking is a third-party open source networking library, built atop Apple’s Foundation URL Loading Library conducting most of the heavy lifting and exposing a set of abstracted wrapper classes for networking capabilities for an iOS or Cocoa Application. 

 

Installing AFNetworking

AFNetworking is available to be installed via source control, directly from the framework’s Github repository, github.com/AFNetworking/AFNetworking.

Gaining access to the library is as simple as cloning the repository and including the AFNetworking folder in your Xcode project. If you use CocoaPods, a dependency-manager for Objective-C, you are able to automate the process of including this library, in addition to other third-party libraries you have, by adding the following to your Podfile:

pod "AFNetworking", "~> 2.0”

 

AFNetworking usage requirements

AFNetworking version 2.0 onwards requires at least iOS 6.0 or Mac OS X 10.8. AFNetworking 1.x however is compatible with older versions of iOS and MAC OS X, but please refer to the release notes for specific minimum requirements.

AFNetworking Architecture

AFNetworking is designed with AFURLConnectionOperation as it’s core backbone, mandated with orchestrating asynchronous requests from start-to-finish. AFURLConnectionOperation is derived from two important Foundation Networking Classes, NSURLConnection and NSOperation.

AFNetworking Arch

Overview of NSURLConnection and NSOperation

The purpose of the NSURLConnection Foundation Networking class in Objective-C is to support the loading of individual NSURLRequest objects asynchronously, whilst providing you with access to receiving informative callbacks representing your network calls, through working with the NSURLConnectionDelegate methods.

NSOperation is an abstract Foundation class, allowing you to create a subclass capable of encapsulating associative code into a single task, to be executed safely, atomically and only once.

NSOperation is usually associated with NSOperationQueue class, which is orchestrated through Apple’s Grand Central Dispatch Concurrency paradigm. Notable features of NSOperation include the abilities to work with state, prioritise operations as well as providing code-unit dependencies.

The composition of AFNetworking

AFNetworking draws on the benefits of both NSURLConnection and NSOperation, in creating the NSOperation subclass, AFURLConnectionOperation,  which also implements the NSURLConnection delegate methods.

AFNetworking also exposes a further subclass of AFURLConnection, AFHTTPRequestOperation which can specifically be used for working with the HTTP/HTTPS protocol. Two further subclasses of AFHTTPRequestOperation, specifically for working with JSON and XML objects are AFJSONRequestOperation and AFXMLRequestOperation classes respectively.

AFNetworking Usage

AFNetworking provides various ways of interacting with remote end-points, from creating individual operations, to using the convenient AFHTTPClient singleton sub-class.

Creating an AFURLConnectionOperation

You first start by creating an NSURLRequest object, pointing to a specific URL resource. You then refer to your newly created request object by creating a new AFURLConnectionOperation.

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

AFURLConnectionOperation *operation = [[AFURLConnectionOperation alloc] initWithRequest:request];

 

Consuming JSON/XML/Images

AFNetworking utilizes the AFHTTPRequestOperation to communicate with HTTP or JSON protocols via requests, providing delegate callback methods for indicating the progress of requests and resolution of the responses.

Developers mostly concern themselves with the more concrete subclasses, AFXMLRequestOperation, AFJSonRequestOperation and the AFImageRequestOperation classes, which return objects of the types their class names suggest. Consuming a JSON or XML or Image is as simple as creating an AFHTTPRequestOperation object block, as follows:

 

AFJSONRequestOperation *operation = [AFJSONRequestOperation 
 JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        NSLog(@"Name: %@ %@", [JSON valueForKeyPath:@"first_name"], [JSON valueForKeyPath:@"last_name"]);
    } failure:nil];

 

AFHTTPClient

AFNetworking goes beyond allowing you to make singular HTTP or JSON request operations, but rather provides a more convenient singleton object, AFHTTPClient, which provides  RESTful accessor for a single web service end-point, and making several requests with the same request object.

[[ASubClassofAFHTTPClient sharedClient] getPath:@"/user/441" parameters:nil success:^(id response) {
        NSLog(@"Name: %@", [response valueForKeyPath:@"name"]);
        NSLog(@"Address: %@", [response valueForKeyPath:@"address.street_address"]);
    } failure:nil];

 

The benefit of this class in it’s ability to anticipate for GET, POST, PUT and DELETE verbs, as well as automatically detecting what type of an operation is being called automatically, such as associating a .json extension with the AFJSONRequstOperation as opposed to the AFHTTPRequestOperation.

 

Sessions

In AFNetworking version 2.x, the framework has greatly expanded the capabilities, especially if you are working with iOS 7. One of the iOS 7 extensions include NSURLSession, which replaces the NSURLConnection in most cases, taking advantage of the new Apple Foundation Networking capabilities.

NSURLSession overview

AFURLSessionManager class is tasked with managing NSURLSession objects based on the NSURLSessionConfiguration object, and takes the base NSURLSession and adds improvements on making HTTP requests, whilst exposing delegate methods for session/session data/session downloading. By utilising the sub-classed AFHTTPSessionManager, you get returned a shared singleton object which you are able to parameterise with authentication and other configuration tokens.

Implementing NSURLSession

The following example demonstrates how you would implement an NSURLSessionDownloadTask object, to generate a specific download task request session.

 

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 *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
    return [documentsDirectoryPath URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
    NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];

 

The code does the following;

  1. Declares a session configuration and set’s it policy to the default session configuration.
  2. AFURLSessionManager object is created based on the previously specified configuration.
  3. Creates a URL pointing to to a remote zip file.
  4. Creates an NSURLRequest object which gets assigned the remote zip file URL location.
  5. An NSURLSessionDownloadTask is created, which actually directly writes the response/download to a temporary file, before it gets moved to a permanent location upon download completion. This is a block that provides access to the target path, and NSURLResponse. The block returns a local directory path to which the response will ultimately get saved to.
  6. The completion handler of the NSURLSessionDownloadTask handles post-download or errors for the process.

 

Serialization

AFNetworking 2.0 has also introduces serialization as a wrapper for parsing requests and responses, and for business logic to be encapsulated amongst those calls to and from. The AFURLRequestSerialization protocol encodes HTTP request parameters as query string or entity body representation, so you can customise how the query encoding works to and from more finely.

 

Using AFURLRequestSerialization

The follow example shows you how to include URL strings as encoded query parameters:

NSString *URLString = @"http://example.com";
NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]};
…
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:URLString parameters:parameters];

 

The resulting serialised GET output looks like the following:

 

GET http://example.com?foo=bar&baz[]=1&baz[]=2&baz[]=3

Likewise,  JSON parameterised encoding can be implemented as easily as:

[[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:URLString parameters:parameters];

which results in the following serialized POST:

POST http://example.com/
Content-Type: application/json

{"foo": "bar", "baz": [1,2,3]}

 

UIKit Extensions

AFNetworking also provides some helpful UIKit categories, that extend your normal UIKit framework with convenient networking functions. Whilst by no means an exhaustive list, below you will find some of the more popular categories that automatically come included when you include the AFNetworking folder in your Xcode project.

AFNetworkActivityIndicatorManager links your AFNetworking activities with the status bar activity indicator, controlling whether the activity indicator has started or stopped based on your implemented request operations and tasks.

UIProgressView+AFNetworking displays a progress of specific request operations, to provide your app with visual feedback.

UIImageView+AFNetworking category provides setter methods for setting an image via a URL, downloading the image asynchronously and implementing the set specified cache policy.

 

Stay up to date

Following the AFNetworking framework on it’s github repository, github.com/AFNetworking/AFNetworking allows you to clone the latest stable, as well as nightly revisions.