一:NSOperation
// 1.簡介
// NSOperation實例封裝了需要執行的操作和執行操作所需的數據,并且能夠以并發或非并發的方式執行這個操作。
// NSOperation本身是抽象基類,因此必須使用它的子類,使用NSOperation子類的方式有2種:
// 1> Foundation框架提供了兩個具體子類直接供我們使用:NSInvocationOperation和NSBlockOperation
// 2> 自定義子類繼承NSOperation,實現內部相應的方法
// 2.執行操作
// NSOperation調用start方法即可開始執行操作,NSOperation對象默認按同步方式執行,也就是在調用start方法的那個線程中直接執行。NSOperation對象的isConcurrent方法會告訴我們這個操作相對于調用start方法的線程,是同步還是異步執行。isConcurrent方法默認返回NO,表示操作與調用線程同步執行
// 3.取消操作
// operation開始執行之后, 默認會一直執行操作直到完成,我們也可以調用cancel方法中途取消操作
NSOperation *operation = [[NSOperation alloc] init];
[operation cancel];
// 4.監聽操作的執行
// 如果我們想在一個NSOperation執行完畢后做一些事情,就調用NSOperation的setCompletionBlock方法來設置想做的事情
//①
[operation setCompletionBlock:^(void){
NSLog(@"setCompletionBlock");
}];
//②
operation.completionBlock = ^(void){
};
//************ 二、NSInvocationOperation ************//
// 1.簡介
// 基于一個對象和selector來創建操作。如果你已經有現有的方法來執行需要的任務,就可以使用這個類
// 2.創建并執行操作
NSInvocationOperation *invovationOper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runOne) object:nil];
// 開始執行任務(同步執行)
[invovationOper start];
//************ 三、NSBlockOperation ************//
// 1.簡介
// 能夠并發地執行一個或多個block對象,所有相關的block都執行完之后,操作才算完成
// 2.創建并執行操作
NSBlockOperation *blockOper =[NSBlockOperation blockOperationWithBlock:^(void){
NSLog(@"執行了一個新的操作,線程:%@", [NSThread currentThread]);
}];
// // 開始執行任務(這里還是同步執行)
// [blockOper start];
// 3.通過addExecutionBlock方法添加block操作
[blockOper addExecutionBlock:^(void){
NSLog(@"又執行了1個新的操作,線程:%@", [NSThread currentThread]);
}];
[blockOper addExecutionBlock:^() {
NSLog(@"又執行了1個新的操作,線程:%@", [NSThread currentThread]);
}];
[blockOper addExecutionBlock:^() {
NSLog(@"又執行了1個新的操作,線程:%@", [NSThread currentThread]);
}];
[blockOper start];
// 可以看出,這4個block是并發執行的,也就是在不同線程中執行的,num屬性可以看成是線程的id
//************ 四、自定義NSOperation ************//
// 1.簡介
// 如果NSInvocationOperation和NSBlockOperation對象不能滿足需求, 你可以直接繼承NSOperation, 并添加任何你想要的行為。繼承所需的工作量主要取決于你要實現非并發還是并發的NSOperation。定義非并發的NSOperation要簡單許多,只需要重載-(void)main這個方法,在這個方法里面執行主任務,并正確地響應取消事件; 對于并發NSOperation, 你必須重寫NSOperation的多個基本方法進行實現
2.非并發的NSOperation
比如叫做DownloadOperation,用來下載圖片
1> 繼承NSOperation,重寫main方法,執行主任務
DownloadOperation.h
[java] view plaincopy#import <Foundation/Foundation.h> @PRotocol DownloadOperationDelegate; @interface DownloadOperation : NSOperation // 圖片的url路徑 @property (nonatomic, copy) NSString *imageUrl; // 代理 @property (nonatomic, retain) id<DownloadOperationDelegate> delegate; - (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate; @end // 圖片下載的協議 @protocol DownloadOperationDelegate <NSObject> - (void)downloadFinishWithImage:(UIImage *)image; @end DownloadOperation.m[java] view plaincopy#import "DownloadOperation.h" @implementation DownloadOperation @synthesize delegate = _delegate; @synthesize imageUrl = _imageUrl; // 初始化 - (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate { if (self = [super init]) { self.imageUrl = url; self.delegate = delegate; } return self; } // 釋放內存 - (void)dealloc { [super dealloc]; [_delegate release]; [_imageUrl release]; } // 執行主任務 - (void)main { // 新建一個自動釋放池,如果是異步執行操作,那么將無法訪問到主線程的自動釋放池 @autoreleasepool { // .... } } @end2> 正確響應取消事件
operation開始執行之后,會一直執行任務直到完成,或者顯式地取消操作。取消可能發生在任何時候,甚至在operation執行之前。盡管NSOperation提供了一個方法,讓應用取消一個操作,但是識別出取消事件則是我們自己的事情。如果operation直接終止, 可能無法回收所有已分配的內存或資源。因此operation對象需要檢測取消事件,并優雅地退出執行
NSOperation對象需要定期地調用isCancelled方法檢測操作是否已經被取消,如果返回YES(表示已取消),則立即退出執行。不管是自定義NSOperation子類,還是使用系統提供的兩個具體子類,都需要支持取消。isCancelled方法本身非常輕量,可以頻繁地調用而不產生大的性能損失
以下地方可能需要調用isCancelled:* 在執行任何實際的工作之前* 在循環的每次迭代過程中,如果每個迭代相對較長可能需要調用多次* 代碼中相對比較容易中止操作的任何地方
DownloadOperation的main方法實現如下
[java] view plaincopy- (void)main { // 新建一個自動釋放池,如果是異步執行操作,那么將無法訪問到主線程的自動釋放池 @autoreleasepool { if (self.isCancelled) return; // 獲取圖片數據 NSURL *url = [NSURL URLWithString:self.imageUrl]; NSData *imageData = [NSData dataWithContentsOfURL:url]; if (self.isCancelled) { url = nil; imageData = nil; return; } // 初始化圖片 UIImage *image = [UIImage imageWithData:imageData]; if (self.isCancelled) { image = nil; return; } if ([self.delegate respondsToSelector:@selector(downloadFinishWithImage:)]) { // 把圖片數據傳回到主線程 [(NSObject *)self.delegate performSelectorOnMainThread:@selector(downloadFinishWithImage:) withObject:image waitUntilDone:NO]; } } }轉自: http://blog.csdn.net/q199109106q/article/details/8565923
新聞熱點
疑難解答