AFNetworkingでエラー時にレスポンスを参照する。
- 2015.02.08
- AFNetworking iOS
AFNetworkingはデフォルトでは、HTTPレスポンスコードが200系でない場合、failureブロックを起動するのですが、failureにはresponseObjectが渡されないので、400系や500系が返ってくるとクライアントで処理が細かく行えない。
調べたが、意外とはっきりと記述してある情報がなかった。
例えば、クライアントからのリクエストパラメータが不正だった場合、(100文字の箇所にそれ以上送信したなど)failure一括になってしまい、細かくクライアントに結果を見せることができない。
デフォルトでやる方法はわからないが、参考となるページから、オーバライドで実装した。
まず、AFHTTPSessionManagerをオーバライド
#import <Foundation/Foundation.h> #import <AFNetworking/AFHTTPSessionManager.h> @interface SenatusNetworkManager : AFHTTPSessionManager // このメソッドはお好みで + (SenatusNetworkManager*)manager; + (NSDictionary*)errorResponse:(NSDictionary*)e; + (NSInteger)errorCode:(NSDictionary*)e;
実装ファイルは
@implementation SenatusNetworkManager // 定数 static SenatusNetworkManager* sharedInstance = nil; static NSString* kErrorResponseObjectKey = @"NetworkManagerErrorResponseKey"; static NSString* kErrorCodeObjectKey = @"NetworkingManagerErrorCodeKey"; // メソッドのオーバーライド - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *, id, NSError *))originalCompletionHandler { return [super dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { // エラー時にエラーオブジェクトに詰める if (error && responseObject) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; if (error.userInfo) { // すでにオブジェクトがある場合(存在理由不明) NSMutableDictionary *userInfo = [error.userInfo mutableCopy]; userInfo[kErrorResponseObjectKey] = responseObject; // 参考サイト情報に加え、HTTPステータスコードも保持 userInfo[kErrorCodeObjectKey] = [NSNumber numberWithInteger:[httpResponse statusCode]]; error = [NSError errorWithDomain:error.domain code:error.code userInfo:[userInfo copy]]; } else { // オブジェクトがない場合、生成 error = [NSError errorWithDomain:error.domain code:error.code userInfo:@{kErrorResponseObjectKey: responseObject, kErrorCodeObjectKey:[NSNumber numberWithInteger:[httpResponse statusCode]]}]; } } // オリジナルハンドラーの呼び出し if (originalCompletionHandler) { originalCompletionHandler(response, responseObject, error); } }]; } // シングルトン(特に不要) + (SenatusNetworkManager*)manager { if (!sharedInstance) { sharedInstance = [SenatusNetworkManager new]; } return sharedInstance; } // エラーのレスポンスを受け取るヘルバーメソッド + (NSDictionary*)errorResponse:(NSDictionary*)e { return e[kErrorResponseObjectKey]; } // エラーのステータスコードを受け取るヘルバーメソッド + (NSInteger)errorCode:(NSDictionary*)e { return [e[kErrorCodeObjectKey] integerValue]; }
参考サイト:Accessing the response body in failure blocks with AFNetworking 2
考えてみると、当たり前なのですが、デフォルトで提供されていると思ってしまった。。。
-
前の記事
nginxで403 Forbidden 2015.02.08
-
次の記事
Elasticsearch + KibanaでConnectionFailed 2015.02.08