본문 바로가기

iPhone dev./AFNetworking / ASIHTTP

AFNetworking 기초

기존에 유용하게 쓰던 ASIHTTP가 업데이트가 중지된지 한참 되어(ARC도 지원 안 해주시고..) 대체할만한 wrapper class를 찾던 중 AFNetworking을 추천받았다.

현재 활발하게 업데이트 되고있으며, 간단한 사용법은 다음과 같다.
참조 사이트: https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking
https://github.com/AFNetworking/AFNetworking

불편한 점이 있다면 POST 요청을 할 때 ASIHTTP보다 꽤나 번거롭다는 점이다.
이제 웬만하면 GET으로 보내야겠다는.. ㅎㅎ

예제1:

Download and Parse JSON

AFJSONRequestOperation is the perfect tool for this job. All you need to do is ask it for a particular URL, and it'll give you JSON when it's done:

NSURL *url = [NSURL URLWithString:@"http://httpbin.org/ip"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

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

[operation start];

First, we construct an NSURL object and construct an NSURLRequest object from it. NSURLRequest encapsulates pretty much everything there is for an HTTP request, including url, method (GETPOSTPUTDELETE, etc.), headers, and the body.

We then pass that url request object into AFJSONRequestOperation +JSONRequestOperationWithRequest:success:failure.

The success and failure parameters take block arguments. Blocks are a relatively new and complex feature in Objective-C, so if you're unfamiliar with them, think about reading up on them. Blocks are objects that contain a specified behavior--code that can be executed later.

In the case of our success and failure callback blocks, we're specifying what should happen after the request finishes. The request happens in the background, without locking up or slowing down the app. Depending on whether the response from the server indicates success (e.g. 200 status code and JSON Content-Type), or failure (e.g. 404 status code or unknown MIME type), the code in the corresponding block will be executed.

You'll notice that the argument for success is ^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON). The caret (^) indicates that what follows is part of a block. The other arguments: requestresponse, and JSON are local variables that are passed into the block. In the block, we can use these values to do things like log the contents of the JSON (like in our example), or do more useful things, like populate anNSArray to update the data source of a UITableView.

After constructing the operation object, we have to start it somehow. In the example, we simply send -start, which kicks off the request and returns immediately.

Another option would be to take advantage of the fact that AFJSONRequestOperation, like all of the request operations in AFNetworking, is a subclass of NSOperation. In combination with NSOperationQueue, you can easily have several requests running concurrently (you have the ability to setting a maximum number of operations to run concurrently to keep your network from getting bogged down).

One last note: in addition to JSON, AFNetworking has a handful of request operations that download data and automatically convert it to things like XMLImages, and Property Lists (http://afnetworking.github.com/AFNetworking/Classes/AFPropertyListRequestOperation.html).

Download and Display Images

AFNetworking makes downloading and setting images as simple as getting an image from the project.

Start by adding #import "UIImageView+AFNetworking" to the top of a controller or a view implementation file. This category adds methods toUIImageView, like:

[imageView setImageWithURL:[NSURL URLWithString:@"…"]];

A longer form of this method also allow you to set a placeholder image while the image is downloading.

Use this anytime you need to load a remote image from the server.

Interact with an API, Web Service, or Application

Chances are pretty good that most if not all of the network requests you make are to a single API or web service, like a Rails or Sinatra backend.

If your app talks to a server backend (or a few different ones), then you'll love AFHTTPClient.

AFHTTPClient has everything you need for talking to a web API. It stores a base URL, which you can request relative paths to (e.g. base URL:http://example.com + relative path: /users = http://example.com/users). You can store a common set of header for things like authentication, content type, and language preferences, which will be added to any request you make with the client. Best of all, it will even automatically figure out how to parse your server response, so JSON requests give you JSON objects, XML requests give you parser objects, etc.

Here are some guidelines on how best to use AFHTTPClient:

  • Create a subclass for each service endpoint you hit. For instance, if you're writing a social network aggregator, you might want a client for Twitter, one for Facebook, another for Instragram, and so on.
  • In HTTP client subclasses, create a class method that returns a shared singleton instance. This way, you can configure and use a single client to use throughout the entire app.
  • Want to upload a file? Check out -multipartFormRequestWithMethod:path:parameters:constructingBodyWithBlock:. In the block, send the multipart form data builder -appendPartWithFileData:name:fileName:mimeType:
  • If you need to send request parameters as JSON, simply set the parameterEncoding property to AFJSONParameterEncoding.
  • If you need to configure or hold a reference to a request operation before it's enqueued into the client's operation queue, use-HTTPRequestOperationWithRequest:success:failure. Likewise with the URL request object, use requestWithMethod:path:parameters.

A good example of an AFHTTPClient subclass can be found in the example project: AFAppDotNetAPIClient. Use it as a starting point for your own client.


예제 2:


Overview

AFNetworking is architected to be as small and modular as possible, in order to make it simple to use and extend.

Core
AFURLConnectionOperationAn NSOperation that implements the NSURLConnection delegate methods.
HTTP Requests
AFHTTPRequestOperationA subclass of AFURLConnectionOperation for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request.
AFJSONRequestOperationA subclass of AFHTTPRequestOperation for downloading and working with JSON response data.
AFXMLRequestOperationA subclass of AFHTTPRequestOperation for downloading and working with XML response data.
AFPropertyListRequestOperationA subclass of AFHTTPRequestOperation for downloading and deserializing objects withproperty list response data.
HTTP Client
AFHTTPClientCaptures the common patterns of communicating with an web application over HTTP, including:
  • Making requests from relative paths of a base URL
  • Setting HTTP headers to be added automatically to requests
  • Authenticating requests with HTTP Basic credentials or an OAuth token
  • Managing an NSOperationQueue for requests made by the client
  • Generating query strings or HTTP bodies from an NSDictionary
  • Constructing multipart form requests
  • Automatically parsing HTTP response data into its corresponding object representation
  • Monitoring and responding to changes in network reachability
Images
AFImageRequestOperationA subclass of AFHTTPRequestOperation for downloading and processing images.
UIImageView+AFNetworkingAdds methods to UIImageView for loading remote images asynchronously from a URL.

Example Usage

XML Request

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://api.flickr.com/services/rest/?method=flickr.groups.browse&api_key=b6300e17ad3c506e706cb0072175d047&cat_id=34427469792%40N01&format=rest"]];
AFXMLRequestOperation *operation = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
  XMLParser.delegate = self;
  [XMLParser parse];
} failure:nil];
[operation start];

Image Request

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
[imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]];

API Client Request

// AFAppDotNetAPIClient is a subclass of AFHTTPClient, which defines the base URL and default HTTP headers for NSURLRequests it creates
[[AFAppDotNetAPIClient sharedClient] getPath:@"stream/0/posts/stream/global" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
    NSLog(@"App.net Global Stream: %@", JSON);
} failure:nil];

File Upload with Progress Callback

NSURL *url = [NSURL URLWithString:@"http://api-base-url.com"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"avatar.jpg"], 0.5);
NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/upload" parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
    [formData appendPartWithFileData:imageData name:@"avatar" fileName:@"avatar.jpg" mimeType:@"image/jpeg"];
}];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
    NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
}];
[operation start];

Streaming Request

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/encode"]];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.inputStream = [NSInputStream inputStreamWithFileAtPath:[[NSBundle mainBundle] pathForResource:@"large-image" ofType:@"tiff"]];
operation.outputStream = [NSOutputStream outputStreamToMemory];
[operation start];

'iPhone dev. > AFNetworking / ASIHTTP' 카테고리의 다른 글

AFNetworking POST 요청 보내기  (0) 2012.11.26
ASIHTTP를 이용한 request/response  (0) 2011.08.08