iOS-----使用NSOperation與NSOperationQueue實現多線程,nsoperationqueue
使用NSOperation與NSOperationQueue實現多線程
NSOperation與NSOperationQueue的基本理論如下。
NSOperationQueue |
代表一個FIFO的隊列,它負責管理系統提交的多個NSOperation,NSOperationQueue底層維護一個線程池,會按順序啟動線程來執行提交給該隊列的NSOperation任務 |
NSOperation |
代表一個多線程任務。NSOperation還有NSInvocationOperation、NSBlockOperation兩個子類。NSOperation有兩種使用方式:①開發人員實現NSOperation的子類;②開發人員直接使用NSInvocationOperation或NSBlockOperation子類。 |
使用NSOperation、NSOperationQueue開發多線程非常簡單,只要如下兩步 |
1 |
建立NSOperationQueue隊列,並為該隊列設定相關屬性。 |
2 |
建立NSOperation子類的對象,並將該對象提交給NSOperationQueue隊列,該隊列將會按順序依次啟用每個NSOperation。 |
NSOperationQueue負責管理、執行所有的NSOperation,它底層維護著一個線程池,開發人員提交的NSOperation正是由該線程池中的線程負責執行的。NSOperationQueue提供了如下常用方法。 |
|
|
|
|
|
使用NSInvocationOperation和NSBlockOperation
NSInvocationOperation和NSBlockOperation都是NSOperation的子類,都可在程式中直接使用,用於封裝需要非同步執行的任務。
NSInvocationOperation和NSBlockOperation在用法上非常相似,區別是NSInvocationOperation用於將特定對象的特定方法封裝成NSOperation,而NSBlockOperation則用於將代碼封裝成NSOperation。
建立NSInvocationOperation的程式碼片段如下:
建立NSBlockOperation的程式碼片段如下:
一旦得到NSOperation對象之後,將NSOperation對象提交給NSOperationQueue即可。
執行個體:使用NSBlockOperation下載圖片
下面是該執行個體的視圖控制器類的實現部分代碼。
1 @implementation ViewController 2 3 NSOperationQueue* queue; 4 5 - (void)viewDidLoad 6 7 { 8 9 [super viewDidLoad];10 11 queue = [[NSOperationQueue alloc] init];12 13 // 設定該隊列最大支援10個並發線程14 15 queue.maxConcurrentOperationCount = 10;16 17 }18 19 - (IBAction)clicked:(id)sender20 21 {22 23 NSString* url = @” http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg”;24 25 // 以傳入的代碼塊作為執行體,建立NSOperation26 27 NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{28 29 // 從網路擷取資料30 31 NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];32 33 // 將網路資料初始化為UIImage對象34 35 UIImage *image = [[UIImage alloc] initWithData: data];36 37 if(image != nil)38 39 {40 41 // 在主線程中執行updateUI:方法42 43 [self performSelectorOnMainThread:@selector(updateUI:)44 45 withObject:image waithUntilDone:YES];// ① 46 47 }48 49 else50 51 {52 53 NSLog(@”---下載圖片出現錯誤---”);54 55 }56 57 }];58 59 // 將NSOperation添加給NSOperationQueue60 61 [queue addOperation:operation];62 63 }64 65 - (void)updateUI:(UIImage*)image66 67 {68 69 self.iv.image = image;70 71 }72 73 @end
該程式建立了一個NSBlockOperation對象,接下來將該對象提交給NSOperationQueue即可.由於該代碼塊將會線上程中執行,因此程式在①號代碼處調用了performSelectorOnMainThread:withObject: waitUntilDone:方法在主線程中更新iv控制項顯示的圖片.
定義NSOperation子類
NSOperation一般不會直接拿來使用,而是選擇建立它的子類,建立NSOperation的子類需要重寫一個方法:- (void)main,該方法的方法將作為NSOperationQueue完成的任務。
下面程式示範了使用NSOperation的子類來下載網狀圖片。該樣本的介面與前面介紹的使用NSThread下載圖片的介面基本相似,只是該程式將會使用NSOperation的子類來啟動多線程執行下載。該樣本的介面上同樣只有一個UIImageView和一個UIButton,程式為UIButton的“Touch Up Inside”時間綁定clicked:事件處理方法。
下面是LCDownImageOperation類的介面部分代碼。
代 碼 片 段 |
1 LCDownLoadImageOperation.h檔案 2 3 #import<Foundation/Foundation.h> 4 5 // 定義NSOperation的子類 6 7 @interface LCDownImageOperation:NSOperation 8 9 @property (nonatomic, strong)NSURL* url;10 11 @property (nonatomic, weak)UIImageView* imageView;12 13 - (id)initWithURL:(NSURL*)url imageView:(UIImageView*)iv;14 15 @end16 17 LCDownLoadImageOperation.m檔案18 19 @implementation LCDownLoadImageOperation20 21 - (id)initWithURL:(NSURL*)url imageView:(UIImageView*)iv22 23 {24 25 self = [super init];26 27 if(self)28 29 {30 31 _imageView = iv;32 33 _url = url;34 35 }36 37 return self;38 39 }40 41 // 重寫main方法,該方法將作為線程執行體42 43 - (void)main44 45 {46 47 // 從網路擷取資料48 49 NSData *data = [[NSData alloc] initWithContentsOfURL:self.url];50 51 // 將網路資料初始化為UIImage對象52 53 UIImage *image = [[UIImage alloc] initWithData;data];54 55 if(image !=nil)56 57 {58 59 // 在主線程中執行updateUI:方法60 61 [self performSelectorOnMainThread:@selector(updateUI:)62 63 withObject:image waitUntilDone:YES];// ①64 65 }66 67 else68 69 {70 71 NSLog(@”+++下載圖片出現錯誤+++”);72 73 }74 75 }76 77 - (void)updateUI:(UIImage*)image78 79 {80 81 self.imageView.image = image;82 83 }84 85 @end |
說明 |
上面的代碼建立了NSOperation類的子類,並重寫了main方法,該方法將會作為該NSOperation所啟動線程的執行體----也就是代表該線程要完成的任務.由於main方法的代碼將會在新線程中執行,因此程式同樣調用了performSelectorOnMainThread:withObject:waitUntilDone:方法在主線程中更新iv控制項顯示的圖片. |
程式碼片段 |
建立了該NSOperation的子類之後,接下來只要建立該子類的執行個體,並將它提交給NSOperationQueue即可.視圖控制器類的實現部分使用了LCDownImageOperation從網路下載圖片.下面是視圖控制器類的實現部分代碼. 1 ViewController.m 2 3 @implementation ViewController 4 5 NSOperationQueue *queue; 6 7 - (void)viewDidLoad 8 9 {10 11 [super viewDidLoad];12 13 queue = [[NSOperationQueue alloc] init];14 15 // 設定該隊列最大支援10個並發線程16 17 queue.maxConcurrentOperationCount = 10;18 19 }20 21 - (IBAction)clicked:(id)sender22 23 {24 25 // 定義要載入的圖片的URL26 27 NSURL *url = [NSURL URLWithString:@” http://img2.imgtn.bdimg.com/it/u=194240101,2532182839&fm=21&gp=0.j pg”];28 29 // 建立LCDownImageOperation對象30 31 LCDownImageOperation* operation = [[LCDownImageOperation alloc] initWithURL:url imageView:self.iv];32 33 // 將NSOperation的子類的執行個體提交給NSOperationQueue34 35 [queue addOperation:operation];36 37 }38 39 @end |
說明 |
上面程式中的代碼就是使用LCDownImageOperation實現多線程下載的關鍵代碼,只要建立LCDownImageOperation執行個體,然後將該執行個體提交給NSOperationQueue即可. |
小結 |
iOS提供了3種多線程支援:①使用NSThread開發多線程應用;②使用GCD實現多線程;③使用NSOperation和NSOperationQueue實現多線程. |
|
|