iOS 多線程--NSOperation

一、NSOperation介紹:基本語法

NSOperation在iOS4后也基于GCD實現,但是相對于GCD來說可控性更強,并且可以加入操作依賴。NSOperation是一個抽象類,系統為我們提供了NSBlockOperation和NSInvocationOperation兩個子類,并且可以創建繼承自NSOperation的自定義類。相比于GCD,NSOperation類更加面向對象,開發者除了不需要去了解線程相關的概念之外,甚至連GCD中需要了解的異步/同步、并行/串行都不太需要深入了解,開發者只要懂得任務和隊列即可。

1、NSOperation的子類

由于NSOperation是一個抽象類,因此不能夠直接使用NSOperation,但蘋果提供了兩個NSOperation的子類,NSBlockOperation和NSInvocationOperation,除此之外,我們還可以自定義NSOperation的子類。

二、NSOperation介紹:線程間通信

在NSOperationQueue類中,也可以獲取主線程隊列,相關更新UI的任務必須放在主隊列中完成。

下方示例中,當點擊開始下載按鈕后,會創建一個NSBlockOperation對象,放在一個普通隊列中執行,開始下載網絡圖片。此時,由于下載任務是在非主線程中進行的,所以界面上的switch按鈕是可以點擊的。等下載完成后,需要在下載任務中返回主線程去設置UI界面。

Paste_Image.png
- (IBAction)startBtnAction:(id)sender {
    NSBlockOperation *downloadTask = [NSBlockOperation blockOperationWithBlock:^{
    //下載網絡圖片
    NSString *urlString = @"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRc3Rs3zHlmPEdusO8G_I1xHyKsYUujL9ZX76nfgkVVu69oU_gosw";
    NSURL *url = [NSURL URLWithString:urlString];
    NSData *imageData = [NSData dataWithContentsOfURL:url];
    UIImage *image = [UIImage imageWithData:imageData];
    //返回主線程設置ui
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    [mainQueue addOperationWithBlock:^{
        self.imageView.image = image;
    }];
}];
//創建queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:downloadTask];
}

三、NSOperation介紹:任務間的執行依賴

NSOperation中提供了更加方便直觀的方式來設置任務執行的先后順序關系。通過NSOperation類中的addDependency方法,即可添加任務的之間的依賴關系。由于addDependency是NSOperation類中的方法,與隊列無關,因此也可以針對不同隊列中的任務設置任務執行的先后依賴關系。

下方的示例中,有3個任務依次順序執行,先依次下載兩張圖片,圖片下載完成后,需要返回主線程去更新界面上的UIImageView,等圖片下載并刷新界面完成后,第三個任務是更新界面上的下載狀態Label。這3個任務的執行有先后依賴關系。

Paste_Image.png
- (IBAction)startBtnAction:(id)sender {
    //創建兩個任務,兩個任務完成后,返回主線程執行第三個更新Label的任務
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        //下載圖片
        NSString *urlString = @"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRc3Rs3zHlmPEdusO8G_I1xHyKsYUujL9ZX76nfgkVVu69oU_gosw";
        NSURL *url = [NSURL URLWithString:urlString];
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image1 = [UIImage imageWithData:imageData];
    
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            self.imageView1.image = image1;
        }];
    }];

    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        //下載圖片
        NSString *urlString = @"https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQ6RwzhikGicc2R-tiySq7A1K8g40apnXtryI31CO3JxW7IEIUJ_Q";
        NSURL *url = [NSURL URLWithString:urlString];
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *image2 = [UIImage imageWithData:imageData];
    
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
            self.imageView2.image = image2;
        }];
    
    }];
    NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
        [mainQueue addOperationWithBlock:^{
           self.titleLab.text = @"下載完成";
        }];
    }];

    //設置任務之間的執行依賴關系
    [task3 addDependency:task1];
    [task3 addDependency:task2];
    [task2 addDependency:task1];
    //創建隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    //添加任務到隊列
    [queue addOperation:task1];
    [queue addOperation:task2];
    [queue addOperation:task3];
}

四、NSOperation與GCD的區別

  • GCD是底層的C語言構成的API,而NSOperationQueue及相關對象是Objc的對象。在GCD中,在隊列中執行的是由block構成的任務,這是一個輕量級的數據結構;而NSOperation作為一個對象,為我們提供了更多的選擇;
  • 在NSOperationQueue中,我們可以隨時取消已經設定要準備執行的任務(當然,已經開始的任務就無法阻止了),而GCD沒法停止已經加入queue的block(其實是有的,但需要許多復雜的代碼);
  • NSOperation能夠方便地設置依賴關系,我們可以讓一個Operation依賴于另一個Operation,這樣的話盡管兩個Operation處于同一個并行隊列中,但前者會直到后者執行完畢后再執行;
    我們能將KVO應用在NSOperation中,可以監聽一個Operation是否完成或取消,這樣子能比GCD更加有效地掌控我們執行的后臺任務;
  • 在NSOperation中,我們能夠設置NSOperation的priority優先級,能夠使同一個并行隊列中的任務區分先后地執行,而在GCD中,我們只能區分不同任務隊列的優先級,如果要區分block任務的優先級,也需要大量的復雜代碼;
  • 我們能夠對NSOperation進行繼承,在這之上添加成員變量與成員方法,提高整個代碼的復用度,這比簡單地將block任務排入執行隊列更有自由度,能夠在其之上添加更多自定制的功能。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 和GCD的對比 操作隊列,比GCD更早,GCD在設計上很多都是基于操作隊列的原理構建的。在iOS4之后,操作隊列的...
    doudo閱讀 190評論 0 0
  • 1. NSOperation簡介 在某些情況下,執行后臺任務GCD不一定是最好的方式,還有一種技術叫做操作隊列NS...
    Claire_wu閱讀 1,054評論 0 0
  • NSOperation是蘋果提供給我們的一套多線程解決方案。實際上它是在ios4后基于GCD開發的,但是比GCD擁...
    艷曉閱讀 224評論 0 2
  • 一、簡介 NSOperation 的作用NSOperation 是對 GCD 的一層封裝,更加面向對象。 配合使用...
    hrscy閱讀 447評論 0 3
  • 世界上最深情的話,往往都是普通的日常用語。 我爸不抽煙不喝酒不賭博。但我最近發現,我爸可能是“毒爸”。 對子女“有...
    看賞閱讀 891評論 3 5