在网络应用程序中,经常需要多任务连接来提高程序的性能。比如多任务下载,多任务HTTP请求等,即线程控制模型中的工作群模型。使用 NSOperation 可以很容易实现这个功能。下面就以使用NSOperation处理并行的HTTP请求为例子,说明其用法。
首先准备一个 NSOperation 的子类,用于处理 HTTP 请求。
1 2 3 4 5 6 7 8 | @interface RequestOperation : NSOperation { NSURLRequest* _request; NSMutableData* _data; } - (id)initWithRequest:(NSURLRequest *)request; @end |
下面是实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | @implementation RequestOperation - (id)initWithRequest:(NSURLRequest *)request { if (self = [self init]) { _request = [request retain]; _data = [[NSMutableData data] retain]; } return self; } - (void)dealloc { [_request release]; [_data release]; [super dealloc]; } // 如果不载下面的函数,会出错 - (BOOL)isConcurrent { return YES; } // 开始处理 - (void)start { if (![self isCancelled]) { // 以异步方式处理事件 [NSURLConnection connectionWithRequest:_request delegate:self]; } } // 取得数据 - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { // 添加数据 [_data appendData:data]; } // HTTP请求结束 - (void)connectionDidFinishLoading:(NSURLConnection*)connection { } @end |
如果没有重载 isConcurrent 函数,缺省是返回NO,就是说只能以同步的方式处理。而如果又使用了connectionWithRequest:delegate: 以异步方式处理事件后,会产生下面的错误信息:
1 | _NSAutoreleaseNoPool(): Object 0x18a140 of class NSURLConnection autoreleased with no pool in place - just leaking |
然后在你的 Controller 类中用 NSOperationQueue 来处理各个任务。
1 2 3 4 5 | @interface xxViewController : UIViewController { NSOperationQueue* _queue; } @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @implementation xxViewController - (IBAction)buttonClicked:(id) sender { _queue = [[NSOperationQueue alloc] init]; // 第一个请求 NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com"]]; RequestOperation* operation = [[RequestOperation alloc] initWithRequest:request]; [operation autorelease]; // 第二个请求 NSURLRequest* request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.yahoo.co.jp"]]; RequestOperation* operation2 = [[RequestOperation alloc] initWithRequest:request2]; [operation2 autorelease]; // 开始处理 [_queue addOperation:operation]; } @end |
以上,用 NSOperation 来并行处理不同的任务,使用 NSOperationQueue 来控制复数的 NSOperation,并且可以限制Queue的大小,而不是无限制的使用任务。当一个任务完成,就执行待机中的任务。