iOSネットワークリクエスト(非同期)
前回に引き続き, ネットワークリクエストです。非同期で実際に利用されるコードを書きます。
ここでは, いくつかのプロとコロルを実装します。このサンプルでは, HTTPSはつかいません。
今まで実現できなかった, ダウンロードのプログレスや状態検出等ができます。
比較的データ量のある処理などに利用するとよいでしょう。
HTTPSは次の回にまわすか。
サンプル
NSURLConnectionDataDelegate, NSURLConnectionDelegate
を実装します。
ヘッダ
@interface AsyncSample : NSObject<NSURLConnectionDataDelegate, NSURLConnectionDelegate> @end
パラメータの外部公開を省略しています。
コード
@interface AsyncSample () @property (nonatomic) NSString *srcURL; @property (nonatomic) NSURLConnection *conn; @property (nonatomic) long total; @property (nonatomic) NSMutableData *downloadData; @end @implementation AsyncSample -(void)clear { self.total = 0; self.downloadData = [[NSMutableData alloc] init]; } -(void)start { NSURL *url = [NSURL URLWithString:self.srcURL]; NSURLRequest *req = [NSURLRequest requestWithURL:url]; self.conn = [NSURLConnection connectionWithRequest:req delegate:self]; // Start the connection [self.conn start]; } -(void)startWithRunLoop { NSURL *url = [NSURL URLWithString:self.srcURL]; NSURLRequest *req = [NSURLRequest requestWithURL:url]; self.conn = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:NO]; // Main roop [self.conn scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [self.conn start]; } #pragma mark - #pragma mark - Delegate -(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response { // Redirect? // You can add additional things for request return request; } #pragma mark - Complete Response -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // Get complete response NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if ( httpResponse.statusCode != 200 ) { // Something wrong. NSLog(@"Something wrong"); [connection cancel]; return; } } #pragma mark - Receive Data -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // How many bytes in this chunk self.total += [data length]; // Add total [self.downloadData appendData:data]; } #pragma mark - Failed -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog(@"Load failed with error %@", [error localizedDescription]); // Error handling // Close file delete tmp file or something } #pragma mark - Entire request has benn loaded, data was finished -(void) connectionDidFinishLoading:(NSURLConnection *)connection { // File operation or complete operations } @end
必要のないコードも一部混じっていますが, clearで初期化, startで処理をスタートしています。
残りはプロトコルの実装です。
エラー処理など一部省略しています
self.conn = [NSURLConnection connectionWithRequest:req delegate:self];
でdelegateを設定して, 処理をdelegationしています。
Protocol
実装しているメソッドを簡単にみていきます
メソッド | 説明 |
---|---|
-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response | リダイレクト処理が入った場合に実行 |
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response | レスポンスが返ってきたとき |
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data | 何かしらデータをダウンロードした場合(データを得るたびに実行) |
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error | 失敗した場合(何かエラーが発生したらその時点で) |
-(void) connectionDidFinishLoading:(NSURLConnection *)connection | 処理が完全に終了 |
ファイルのダウンロードだけが目的ならライブラリASIHTTPRequestとかを使った方が早い気がします。セキュリティやどうしても何か処理を入れたい場合は, じっくり実装するしかないですね。