Skip to content
Mattt Thompson edited this page Dec 28, 2012 · 6 revisions

Why not just use NSURLConnection?

While NSURLConnection provides +sendAsynchronousRequest:queue:completionHandler: and +sendSynchronousRequest:returningResponse:error:, there are many benefits to using AFNetworking:

  • AFURLConnectionOperation and its subclasses inherit from NSOperation, which allows requests to be cancelled, suspended / resumed, and managed by an NSOperationQueue.
  • AFURLConnectionOperation also allows you to easily stream uploads and downloads, handle authentication challenges, monitor upload and download progress, and control the caching behavior or requests.
  • AFHTTPRequestOperation and its subclasses distinguish between successful and unsuccessful requests based on HTTP status codes and content type.
  • AFNetworking includes media-specific request operations that transform NSData into more useable formats, like JSON, XML, images, and property lists.
  • AFHTTPClient provides a convenient interface to interact with web services, including default headers, authentication, network reachability monitoring, batched operations, query string parameter serialization, and multipart form requests.
  • UIImageView+AFNetworking adds a convenient way to asynchronously loads images.

Does AFNetworking have any caching mechanisms built-in?

AFNetworking takes advantage of the caching functionality already provided by NSURLCache and any of its subclasses.

We recommend you try out Pete Steinberger's fork of SDURLCache, which provides disk caching, which is not otherwise implemented by NSURLCache on iOS. You may find it useful to set ignoreMemoryOnlyStoragePolicy to YES for the SDURLCache instance, which will ensure that images will be cached to disk more consistently for offline use (which, as reported in the SDURLCache README, iOS 5 supports, but only for http, so it still remains a good option if you want to support iOS 4 or https)

How do I upload a file?

Uploading a file is really just constructing an HTTP multi-part form body for a URL request.AFHTTPClient provides several helper functions that make this easy.

To create the request object, you would do something like:

NSData *imageData = UIImagePNGRepresentation(image);
NSURLRequest *request = [client multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData> formData) {
  [formData appendPartWithFileData:imageData mimeType:@"image/png" name:@"avatar"];
}];

You could then pass request into any request operation, like AFJSONRequestOperation -JSONRequestOperationWithRequest:success:failure:.

How do I download a file?

Use the outputStream property of AFURLConnectionOperation or its subclasses, setting it to an NSOutputStream that streams to a file at a specified path:

operation.outputStream = [NSOutputStream outputStreamToFileAtPath:@"download.zip" append:NO];

This is especially useful when you're downloading anything relatively large (more than a few MB), since the contents of the file will be streamed directly to the file, rather than being stored in memory.

I'm getting a a warning "SystemConfiguration framework not found in project", how do I fix this?

AFNetworking has optional dependencies of the SystemConfiguration and CoreServices / MobileCoreServices frameworks. While they are not required to use AFNetworking, their inclusion turns on network reachability monitoring and file MIME type detection on uploaded files, respectively. Not including them triggers a compiler warning. To include these frameworks in your project, and silence these warnings, do the following two things:

  1. Go to the "Build Phases" tab for your project target
  2. Under "Link Binary with Libraries", click the + button and add SystemConfiguration as well as MobileCoreServices on iOS, or CoreServices on Mac OS X.
  3. In your precompiled headers file, Prefix.pch, add the following lines under #import <Foundation/Foundation.h>:
#import <SystemConfiguration/SystemConfiguration.h>
#import <MobileCoreServices/MobileCoreServices.h> // or #import <CoreServices/CoreServices.h> for Mac OS X

How do I keep requests running in the background after the app has been dismissed?

As of AFNetworking 1.0RC1, AFURLConnectionOperation has a setShouldExecuteAsBackgroundTaskWithExpirationHandler: method that can be used to have operations continue when an app is dismissed and enters the background:

[self setShouldExecuteAsBackgroundTaskWithExpirationHandler:^{
  // Clean up anything that needs to be handled if the request times out
  // It may be useful to initially check whether the operation finished or was cancelled
}];

How do I send JSON parameters in my request?

If you're using AFHTTPClient, set the parameterEncoding property to AFJSONParameterEncoding. Any method on that HTTP client with a parameters argument will now encode the passed object into a JSON string and set the HTTP body and Content-Type header appropriately.

Otherwise, you can do this manually by adding the header Content-Type: application/json, and setting the body of your request to a JSON string.

How do I track upload or download progress?

AFURLConnectionOperation provides the methods setUploadProgressBlock: and setDownloadProgressBlock:. Each method takes a single parameter, which is a block that will be executed periodically during the lifetime of the request. The block has no return type and takes 3 arguments: the number of bytes read or written for this callback, the total number of bytes read or written so far, and the total number of bytes expected to be read or written.

If you wanted to update a progress bar, you could set the respective progress block to set the progress amount to total number bytes read or written divided by the expected number, normalized between 0.0 and 1.0. UI updates based on this value will update asynchronously as the request is being made.

How do I make streaming requests?

All request operations have the inputStream and outputStream property. To download data as its sent from the server, set the outputStream property with an NSOutputStream object. All uploads using AFHTTPClient -multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock: are automatically streamed; you can alternatively set the inputStream yourself.

Why are some upload requests failing with the error "request body stream exhausted"? What does that mean, and how do I fix this?

When uploading over a 3G or EDGE connection, requests may fail with "request body stream exhausted". Using -throttleBandwidthWithPacketSize:delay: your multipart form construction block, you can set a maximum packet size and delay according to the recommended values (kAFUploadStream3GSuggestedPacketSize and kAFUploadStream3GSuggestedDelay). This lowers the risk of the input stream exceeding its allocated bandwidth. Unfortunately, as of iOS 6, there is no definite way to distinguish between a 3G, EDGE, or LTE connection. As such, it is not recommended that you throttle bandwidth based solely on network reachability. Instead, you should consider checking for the "request body stream exhausted" in a failure block, and then retrying the request with throttled bandwidth.

How do I wait for completionBlock to finish?

The short answer is: you don't. Access the responseObject properties as needed once the operation is finished.

If you are using batched operations, or chaining operations in a complex way, you may run into issues caused by there not being any guarantees of when and how long an operation's completionBlock is run. Keep in mind that the default completionBlocks often do nothing more than serialize response objects, which are accessible as a property on the operation. So, for example, if you wish to create a set of records from the JSON of multiple operations in a batch, you could omit completionBlocks for each operation, and instead enumerate each of the finished operations in the batch callback and access the responseJSON property directly.

Why don't I get JSON / XML / Property List in my HTTP client callbacks?

These content types are only returned as the response object for requests when 1) the HTTP client has registered the appropriate AFHTTPRequestOperation subclass with -registerHTTPOperationClass:, and 2) the request Accept HTTP header is appropriate for the content type requested. Not doing this may result in getting an NSData instance of the success or failure callback blocks of methods like getPath:parameters:success:failure.

So to work with JSON data, for example, do [client registerHTTPOperationClass:[AFJSONRequestOperation class]] and [client setDefaultHeader:@"Accept" value:@"application/json"] when initializing the HTTP client.

How can I wait for a group of requests to finish before processing them?

Use AFHTTPClient -enqueueBatchOfHTTPRequestOperationsWithRequests:progressBlock:completionBlock: or -enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock: to batch a series of requests together, specifying a callback for when all of the requests have finished. As mentioned in the question about waiting for completion blocks to finish, you may not want to set completion blocks on each individual operation, and instead access the response object properties directly in the batch completion block.

Can I use AFNetworking for OAuth?

Yes. Check out AFOAuth2Client.

What's the best way to test/mock network requests with AFNetworking?

Use NSURLProtocol to intercept requests before they hit the network, and return canned responses using local data. More information about this technique can be found in this blog post by Claus Broch.

There are also some great third-party libraries, including Nocilla and OHHTTPStubs, which provide block-based interfaces for NSURLProtocol HTTP stubbing and mocking.

Is AFNetworking compatible with ARC?

Yes--AFNetworking uses ARC in the master branch as of September 14, 2012. Non-ARC builds are available in 0.10.x releases.

How do I use gzip compression with AFNetworking?

AFNetworking does not include any mechanisms for gzip compression, but you can easily compress data manually or by using libraries like Godzippa (you will likely need to add the zlib library in your build target). Simply take the HTTPBody from a NSMutableURLRequest, compress the data, and re-set it before creating the operation using the request. Gzip decompression from server responses is already built into AFNetworking, as NSURLConnection will automatically decompress responses with the Content-Encoding: gzip HTTP header.

How do I generate documentation?

Docsets can be generated from the AFNetworking source code using appledoc. Install appledoc, and in the root AFNetworking project directory, enter the following command:

$ appledoc --project-name="AFNetworking" --project-company="AFNetworking" --company-id="com.afnetworking.afnetworking" AFNetworking/*.h

How is AFNetworking affected by Gowalla's acquisition?

AFNetworking will continue to be released and actively maintained by its creators and contributors under the MIT License.

No matter what happens to Gowalla, AFNetworking is here to stay.

What's with the "AF" prefix?

The "AF" in AFNetworking stands for "Alamofire", which is the former name of the company known today as Gowalla. Alamofire Inc. was named after the Alamo Fire, a hybrid of the Bluebonnet--Texas' state flower.

Using AF is also a nod to the "NS" prefix used in Apple's Foundation framework, which harkens back to its NeXTSTEP roots.