Objective-CでHTTPリクエスト扱うライブラリ作った
sendAsynchronouseRequest個別に書くのはしんどいし、最初は簡単にラップしてBlocksでコールバック渡すのがいいかなーと思ったけどself渡すのにいちいち__weakつけて作るのがめんどくさくなった。
setTimeoutの関数に「var that = self」やるのがめんどくさいあんな感じ。
多分ほぼAPIとのやりとりになるiPhoneアプリのHTTP通信はシンプルでよくて、HTTPリクエストをセットできて個別にコールバックを書けてHTTPレスポンスを受け取れればいい。
あと最近はRESTなAPIも多いのでPUT/DELETEリクエストも使いたいところ。
JS脳なのでこんな感じで書きたいw
$.get(url, params, this.handleSuccess_, this.handleFailure); $.getJSON(url, params, this.handleSuccess_, this.handleFailure);
NSURLRequestはパラメータをセットするのがとてもめんどくさいのでそこはラップするとして。
コールバックをBlocks以外でやるとデリゲートが真っ先に浮かぶわけですが、そうすると1対1になっちゃう。
なんかいいのないかなーと探したらNSInvocationてのがありました。
これを使うとあるオブジェクトにセレクタを引数渡して実行することができる。
こんな感じ。
// Invocationを作って NSInvocation *invocation = nil; NSMethodSignature *sig = [delegate methodSignatureForSelector: someSelector]; if (sig) { invocation = [NSInvocation invocationWithMethodSignature: sig]; [invocation setTarget: delegate]; [invocation setSelector: someSelector]; } // 引数をセットして実行する [invocation setArgument: firstArgument atIndex: 2]; [invocation setArgument: secondArgument atIndex: 3]; [invocation invoke];
これならデリゲートと成功/失敗コールバックを渡して中でNSInvocation作ってsendAsynchronousRequestのcompleteBlock内でよしなにコールバックを実行してあげればいい。
ということでHttpClientライブラリを作ってみた。
waka/CCHttpClient
こんな感じでデリゲートとセレクタを渡して使える。
#import "CCHttpClient" - (void) get: (NSString *)url { CCHttpClient *client = [CCHttpClient clientWithUrl: url]; [client getWithDelegate: @{@"foo": @"bar"} // Query parameters as NSDictionary headers: @{@"application/json": @"Accept"} // HTTP headers as NSDictionary delegate: self success: @selector(handleGetSuccess:result:) failure: @selector(handleGetFailure:error:)]; } - (void) handleGetSuccess: (NSHTTPURLResponse *)response result: (NSData *)result { [SVProgressHUD: showSuccessWithStatus: @"Success!"]; id json = [CCHttpClient responseJSON: result]; // If want JSON data [self updateView: json]; } - (void) handleGetFailure: (NSHTTPURLResponse *)response result: (NSError *)error { [SVProgressHUD: showErrorWithStatus: @"Failure!"]; }
同じようにPOST/PUT/DELETEも使えます。
JSONの扱いどうしようと思ったけど、そこはJSのXHRと同じくレスポンスをそのまま返しちゃって、アプリ側でJSONとして使えばいいかと。