AFNetworking 2.0 のまとめ


## 概要
2.0になってから更にシンプルに記述できるようになっています。

下記が必須要件となっていますので導入前に確認してください。

* Xcode 5以上
* iOS 6.0以上

大きな変更点として[ドキュメント](http://cocoadocs.org/docsets/AFNetworking/2.0.0/Classes/AFHTTPSessionManager.html)にあるようにiOS7以降のサポートのみでよければ`AFHTTPSessionManager`のサブクラスを作成して実装することが推奨されています。
iOS6やそれ以前のバージョンをサポートする場合の選択肢として`AFHTTPRequestOperationManager`が用意されています。

ここでは主に`AFHTTPRequestOperationManager`の使い方について触れておきます。

## 使い方
インストールもCocoaPodsで簡単に導入できますので、下記Podfileをプロジェクトのルート直下に作成してインストールしましょう。

```
platform :ios, '7.0'
pod "AFNetworking", "~> 2.0"
```

インストールできたら後はこの記述のみでJSONにパースするとこまでやってくれます。

```objc
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"http://hoge/sample.json"
      parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"response: %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];
```

POSTでパラメータを設定する場合

```objc
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
NSDictionary* param = @{@"param1" : @"value1", @"param2" : @"value2"};
[manager POST:@"http://hoge/sample.json" parameters:param success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"response: %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];
```

結果が通常のレスポンスの場合

```objc
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
```

として`AFHTTPResponseSerializer`をセットしておきましょう。
でないとJSONのパースエラーになります。

レスポンスがXMLの場合少し面倒です。

```objc
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
// 許可するContentTypeの設定が必要
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/rss+xml"];
```

結果のresponseObjectが`NSXMLParser`なので自前でパースする必要があります。
ここも自動でパースしてくれれば言う事無しです。

他にもリクエストパラメータをJSONにしたい場合には、

```objc
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
```

だけで自動でやってくれます。

## 通信ログについて
通信の詳細なログが見たい時は`AFNetworkActivityLogger`を別途インストールするとリクエストヘッダー、レスポンスヘッダーもログ出力してくれます。

```
platform :ios, '7.0'
pod "AFNetworking", "~> 2.0"
pod "AFNetworkActivityLogger", "~> 2.0"
```

Podfileに`AFNetworkActivityLogger`を追加してインストールします。

`AppDelegate.m -application:didFinishLaunchingWithOptions::`にログを開始する処理を記述します。

```objc
[[AFNetworkActivityLogger sharedLogger] startLogging];
```

ログレベルを`AFLoggerLevelDebug `にすればリクエストヘッダー、レスポンスヘッダーを含む通信のやりとりをログに出力できます。

```objc
[[AFNetworkActivityLogger sharedLogger] setLevel:AFLoggerLevelDebug];
```

GTMHttpFetcherのように通信ログをHTMLファイルで別途出力してくれれば言うことなしなんですけどね。

## キャッシュポリシー、タイムアウトについて

`AFHTTPRequestOperationManager `にはキャッシュポリシーとタイムアウトを設定するパラメータがありません。
現状で対応しようとすると`AFHTTPRequestOperationManager`を継承したクラスを作って下記メソッドを追加するといった個別の対応をする必要があります。
カテゴリを使ってメソッドを追加してもよさそうです。

```objc
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
                     parameters:(NSDictionary *)parameters
                timeoutInterval:(NSTimeInterval)timeoutInterval
                    cachePolicy:(NSURLRequestCachePolicy)cachePolicy
                        success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                        failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters];
    request.timeoutInterval = timeoutInterval;
    request.cachePolicy = cachePolicy;
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    [self.operationQueue addOperation:operation];
    
    return operation;
}
```

もしくは`AFHTTPRequestOperationManager`を使用せず`AFHTTPRequestOperation`を直接使用することでも対応できます。

```objc
NSURL *URL = [NSURL URLWithString:@"http://hoge/sample.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]
                                         initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"response: %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];

[operation start];
```

## セキュリティポリシー
テスト環境などでSSL通信をする際にオレオレ証明書(自己署名証明書)を使っている場合は、`AFHTTPRequestOperationManager`にオレオレ証明書を許可する設定を行うことで通信できます。

```objc
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
// 以降は通常通りAFHTTPRequestOperationManagerを使って通信を行う
```

## まとめ
`NSURLSession`の登場によって今後は`NSURLConnection`がベースとなっている`AFHTTPRequestOperationManager`ではなく`AFHTTPSessionManager`が主流になると思います。
現状ではiOS6のサポートが必要なアプリも多いと思いますので、`AFHTTPRequestOperationManager`をメインに使いつつ、可能なところから`AFHTTPSessionManager`にシフトしていけばよいでしょう。