NSOperation學習記錄

NSOperationQueue和GCD的隊列類型

  1. NSOperationQueue
  • 主隊列[NSOperationQueue mainQueue]
    凡是添加到主隊列中的任務(NSOperation),都會放到主線程中執(zhí)行
  • 非主隊列(其他隊列)

[[NSOperationQueue alloc] init].同時包含了:串行、并發(fā)功能添加到這種隊列中的任務(NSOperation),就會自動放到子線程中執(zhí)行

2.GCD

  • 并發(fā)隊列
    全局、自己創(chuàng)建
  • 串行隊列
    主隊列、自己創(chuàng)建

NSOperation功能

  • 開啟任務
    需要執(zhí)行的操作封裝到一個NSOperation對象中,然后將NSOperation對象添NSOperationQueue中系統(tǒng)會自動將NSOperationQueue中的NSOperation取出來,將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行。NSOperation是個抽象類,并不具備封裝操作的能力,必須使用它的子類,系統(tǒng)提供的子類是
    NSBlockOperation和NSInvocationOperation
//這里是在主線程執(zhí)行的  
self.blockOperation = [NSBlockOperation blockOperationWithBlock:^{  
    NSLog(@"塊內執(zhí)行線程 %@",[NSThread currentThread]);  
}];  
//這里是子線程  
[self.blockOperation addExecutionBlock:^{  
     
    NSLog(@"這是新加的塊方法 %@",[NSThread currentThread]);  
}];  
[self.blockOperation start];  
  
//主線程  
NSInvocationOperation * op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(execute) object:nil];  
[op start];  
  1. 默認情況下,調用了start方法后并不會開一條新線程去執(zhí)行操作,而是在當前線程同步執(zhí)行操作
  • 只有將NSOperation放到一個NSOperationQueue中,才會異步執(zhí)行操作

  • 對于NSBlockOperation 只要block操作數大于1就會執(zhí)行異步操作。
    也可以自定義子類,方法非常簡單只需要繼承NSOperation后將操作寫在main函數就可以。

  • 自己創(chuàng)建自動釋放池(因為如果是異步操作,無法訪問主線程的自動釋放池)。

  • 經常通過- (BOOL)isCancelled方法檢測操作是否被取消,對取消做出響應,對應操作比較耗時的時候。防止不能及時退出

  • NSBlockOperation 只要里面的操作塊大于1就會進行異步操作。

  • 設置依賴
    NSOperation之間可以設置依賴來保證執(zhí)行順序,比如一定要讓操作A執(zhí)行完后,才能執(zhí)行操作B,可以這么寫
    //設置op1依賴op2,不在一個隊列也無所謂,不能相互依賴

NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{  
    NSLog(@"任務1");  
}];  
NSInvocationOperation * op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];  
[op1 addDependency:op2];  
NSOperationQueue * op1queue = [[NSOperationQueue alloc]init];  
[op1queue addOperation:op1];  
NSOperationQueue * op2queue = [[NSOperationQueue alloc]init];  
[op2queue addOperation:op2];  

NSOperationQueue

NSOperation可以調用start方法來執(zhí)行任務,但默認是同步執(zhí)行的如果將NSOperation添加到NSOperationQueue(操作隊列)中,系統(tǒng)會自動異步執(zhí)行NSOperation中的操作。

  1. 添加任務到隊列
- (void)addOperation:(NSOperation *)op;  
- (void)addOperationWithBlock:(void (^)(void))block 
[queue addOperationWithBlock:^{  
    NSLog(@"download1 --- %@", [NSThread currentThread]);  
}];  
[queue addOperationWithBlock:^{  
    NSLog(@"download2 --- %@", [NSThread currentThread]);  
}];  

執(zhí)行的任務順序不是和添加的順序一樣的,沒有必然關系。添加到隊列里面后任務由隊列調度運行,不用start了。

2.可以設置并發(fā)數目

并發(fā)數目設置為1的時候就是串行隊列,大于1的時候就是并行隊列

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 
- (void)cancelAllOperations;可以中斷隊列當前的所有任務

提示:也可以調用NSOperation的- (void)cancel方法取消單個操作
暫停和恢復隊列

- (void)setSuspended:(BOOL)b;// YES代表暫停隊列,NO代表恢復隊列
- (BOOL)isSuspended;

可以監(jiān)聽一個操作的執(zhí)行完畢

- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block;

下面是一個來自小碼哥自己實現圖片緩存的案例

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  
{  
    static NSString *ID = @"app";  
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];  
      
    XMGApp *app = self.apps[indexPath.row];  
    cell.textLabel.text = app.name;  
    cell.detailTextLabel.text = app.download;  
      
    // 先從內存緩存中取出圖片  
    UIImage *image = self.images[app.icon];  
    if (image) { // 內存中有圖片  
        cell.imageView.image = image;  
    } else {  // 內存中沒有圖片  
        // 獲得Library/Caches文件夾  
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];  
        // 獲得文件名  
        NSString *filename = [app.icon lastPathComponent];  
        // 計算出文件的全路徑  
        NSString *file = [cachesPath stringByAppendingPathComponent:filename];  
        // 加載沙盒的文件數據  
        NSData *data = [NSData dataWithContentsOfFile:file];  
          
        if (data) { // 直接利用沙盒中圖片  
            UIImage *image = [UIImage imageWithData:data];  
            cell.imageView.image = image;  
            // 存到字典中  
            self.images[app.icon] = image;  
        } else { // 下載圖片  
            [self.queue addOperationWithBlock:^{  
                // 下載圖片  
                NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]];  
                UIImage *image = [UIImage imageWithData:data];  
                  
                [NSThread sleepForTimeInterval:1.0];  
                  
                // 回到主線程顯示圖片  
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{  
                    cell.imageView.image = image;  
                }];  
                  
                // 存到字典中  
                self.images[app.icon] = image;  
                // 將圖片文件數據寫入沙盒中  
                [data writeToFile:file atomically:YES];  
            }];  
        }  
    }  
    return cell;  
}  
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容