-
Notifications
You must be signed in to change notification settings - Fork 0
Home
While NSURLConnection
provides +sendAsynchronousRequest:queue:completionHandler:
and +sendSynchronousRequest:returningResponse:error:
, there are many benefits to using AFNetworking:
-
AFURLConnectionOperation
and its subclasses inherit fromNSOperation
, which allows requests to be cancelled, suspended / resumed, and managed by anNSOperationQueue
. -
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.
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
)
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:
.
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.
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:
- Go to the "Build Phases" tab for your project target
- Under "Link Binary with Libraries", click the
+
button and addSystemConfiguration
as well asMobileCoreServices
on iOS, orCoreServices
on Mac OS X. - 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
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
}];
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.
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.
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.
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 completionBlock
s for each operation, and instead enumerate each of the finished operations in the batch callback and access the responseJSON
property directly.
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.
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.
Yes. Check out AFOAuth2Client.
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.
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.
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
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.
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.