iOS 多線程--NSOperation

一、NSOperation介紹:基本語法

NSOperation在iOS4后也基于GCD實(shí)現(xiàn),但是相對于GCD來說可控性更強(qiáng),并且可以加入操作依賴。NSOperation是一個(gè)抽象類,系統(tǒng)為我們提供了NSBlockOperation和NSInvocationOperation兩個(gè)子類,并且可以創(chuàng)建繼承自NSOperation的自定義類。相比于GCD,NSOperation類更加面向?qū)ο?,開發(fā)者除了不需要去了解線程相關(guān)的概念之外,甚至連GCD中需要了解的異步/同步、并行/串行都不太需要深入了解,開發(fā)者只要懂得任務(wù)和隊(duì)列即可。

1、NSOperation的子類

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

二、NSOperation介紹:線程間通信

在NSOperationQueue類中,也可以獲取主線程隊(duì)列,相關(guān)更新UI的任務(wù)必須放在主隊(duì)列中完成。

下方示例中,當(dāng)點(diǎn)擊開始下載按鈕后,會創(chuàng)建一個(gè)NSBlockOperation對象,放在一個(gè)普通隊(duì)列中執(zhí)行,開始下載網(wǎng)絡(luò)圖片。此時(shí),由于下載任務(wù)是在非主線程中進(jìn)行的,所以界面上的switch按鈕是可以點(diǎn)擊的。等下載完成后,需要在下載任務(wù)中返回主線程去設(shè)置UI界面。

Paste_Image.png
- (IBAction)startBtnAction:(id)sender {
    NSBlockOperation *downloadTask = [NSBlockOperation blockOperationWithBlock:^{
    //下載網(wǎng)絡(luò)圖片
    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];
    //返回主線程設(shè)置ui
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    [mainQueue addOperationWithBlock:^{
        self.imageView.image = image;
    }];
}];
//創(chuàng)建queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:downloadTask];
}

三、NSOperation介紹:任務(wù)間的執(zhí)行依賴

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

下方的示例中,有3個(gè)任務(wù)依次順序執(zhí)行,先依次下載兩張圖片,圖片下載完成后,需要返回主線程去更新界面上的UIImageView,等圖片下載并刷新界面完成后,第三個(gè)任務(wù)是更新界面上的下載狀態(tài)Label。這3個(gè)任務(wù)的執(zhí)行有先后依賴關(guān)系。

Paste_Image.png
- (IBAction)startBtnAction:(id)sender {
    //創(chuàng)建兩個(gè)任務(wù),兩個(gè)任務(wù)完成后,返回主線程執(zhí)行第三個(gè)更新Label的任務(wù)
    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 = @"下載完成";
        }];
    }];

    //設(shè)置任務(wù)之間的執(zhí)行依賴關(guān)系
    [task3 addDependency:task1];
    [task3 addDependency:task2];
    [task2 addDependency:task1];
    //創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    //添加任務(wù)到隊(duì)列
    [queue addOperation:task1];
    [queue addOperation:task2];
    [queue addOperation:task3];
}

四、NSOperation與GCD的區(qū)別

  • GCD是底層的C語言構(gòu)成的API,而NSOperationQueue及相關(guān)對象是Objc的對象。在GCD中,在隊(duì)列中執(zhí)行的是由block構(gòu)成的任務(wù),這是一個(gè)輕量級的數(shù)據(jù)結(jié)構(gòu);而NSOperation作為一個(gè)對象,為我們提供了更多的選擇;
  • 在NSOperationQueue中,我們可以隨時(shí)取消已經(jīng)設(shè)定要準(zhǔn)備執(zhí)行的任務(wù)(當(dāng)然,已經(jīng)開始的任務(wù)就無法阻止了),而GCD沒法停止已經(jīng)加入queue的block(其實(shí)是有的,但需要許多復(fù)雜的代碼);
  • NSOperation能夠方便地設(shè)置依賴關(guān)系,我們可以讓一個(gè)Operation依賴于另一個(gè)Operation,這樣的話盡管兩個(gè)Operation處于同一個(gè)并行隊(duì)列中,但前者會直到后者執(zhí)行完畢后再執(zhí)行;
    我們能將KVO應(yīng)用在NSOperation中,可以監(jiān)聽一個(gè)Operation是否完成或取消,這樣子能比GCD更加有效地掌控我們執(zhí)行的后臺任務(wù);
  • 在NSOperation中,我們能夠設(shè)置NSOperation的priority優(yōu)先級,能夠使同一個(gè)并行隊(duì)列中的任務(wù)區(qū)分先后地執(zhí)行,而在GCD中,我們只能區(qū)分不同任務(wù)隊(duì)列的優(yōu)先級,如果要區(qū)分block任務(wù)的優(yōu)先級,也需要大量的復(fù)雜代碼;
  • 我們能夠?qū)SOperation進(jìn)行繼承,在這之上添加成員變量與成員方法,提高整個(gè)代碼的復(fù)用度,這比簡單地將block任務(wù)排入執(zhí)行隊(duì)列更有自由度,能夠在其之上添加更多自定制的功能。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 和GCD的對比 操作隊(duì)列,比GCD更早,GCD在設(shè)計(jì)上很多都是基于操作隊(duì)列的原理構(gòu)建的。在iOS4之后,操作隊(duì)列的...
    doudo閱讀 262評論 0 0
  • 1. NSOperation簡介 在某些情況下,執(zhí)行后臺任務(wù)GCD不一定是最好的方式,還有一種技術(shù)叫做操作隊(duì)列NS...
    Claire_wu閱讀 1,104評論 0 0
  • NSOperation是蘋果提供給我們的一套多線程解決方案。實(shí)際上它是在ios4后基于GCD開發(fā)的,但是比GCD擁...
    艷曉閱讀 245評論 0 2
  • 一、簡介 NSOperation 的作用NSOperation 是對 GCD 的一層封裝,更加面向?qū)ο蟆?配合使用...
    hrscy閱讀 473評論 0 3
  • 世界上最深情的話,往往都是普通的日常用語。 我爸不抽煙不喝酒不賭博。但我最近發(fā)現(xiàn),我爸可能是“毒爸”。 對子女“有...
    看賞閱讀 1,050評論 3 5

友情鏈接更多精彩內(nèi)容