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とかを使った方が早い気がします。セキュリティやどうしても何か処理を入れたい場合は, じっくり実装するしかないですね。
