玩轉iOS開發:iOS中的NSOperation開發(一)

CainLuo發表於2019-02-20

文章分享至我的個人技術部落格: https://cainluo.github.io/15019481375874.html


之前, 我們花了小段時間就把GCD給摸了個底, 知道了GCD的操作, 不知道大家有沒有好好去耍耍, 這次我們再來講講, iOS中的多執行緒操作.

NSOperation, NSOperation它是基於GCD的基礎進行封裝的, 雖然GCD簡單, 但是是C風格程式碼, 而NSOperation的話, 它是Objective-C風格的程式碼, 看起來更加的iOS一些, 程式碼讀起來也是比較更加的直觀, 讓我們一起去溜溜看吧~

轉載宣告:如需要轉載該文章, 請聯絡作者, 並且註明出處, 以及不能擅自修改本文.


NSOperation簡介

剛剛我們提到了NSOperation是蘋果爸爸基於GCD的封裝, 程式碼風格是Objective-C, 所以更加簡單易懂, 可讀性也高.

但這裡需要注意一下, NSOperation是需要和NSOperationQueue配合著來使用的, 這是為啥呢?

因為NSOperation單獨使用的話, 它是屬於同步操作, 並不具有開啟新執行緒的功能, 只有配合著NSOperationQueue才能夠實現多執行緒的操作.

我們都知道NSOperation是基於GCD來封裝了, 那麼使用起來也是和GCD差不多, 其中的NSOperation就相當於GCD中的任務, 而NSOperationQueue就相當於GCD中的佇列啦.

那麼使用NSOperation需要三個步驟:

  • 建立任務: 這裡我們需要把執行的任務丟到NSOperation
  • 建立佇列: 建立NSOperationQueue佇列物件
  • 新增任務到佇列中: 最後將NSOperation物件新增到NSOperationQueue中, 這樣就完成了.

在使用的時候, 系統就會自動將NSOperationQueue中的NSOperation取出, 然後就在新執行緒裡完成操作.


NSOperation和NSOperationQueue的基本使用

在開始擼程式碼之前, 我們還得知道一件事, NSOperation它是屬於一個抽象類, 並不能用來封裝任務, 那咋辦呢?

沒關係NSOperation這裡提供三種方法來實現:

  • 使用NSInvocationOperation子類來封裝任務
  • 使用NSBlockOperation子類來封裝任務
  • 使用繼承於NSOperation的子類來封裝任務, 也就是說, 你可以自己寫一個自定義的子類來實現封裝任務

剛剛我們也知道了, 單獨使用NSOperation的時候是屬於同步執行, 所以下面我們會了解三種建立的方式.

NSInvocationOperation

程式碼擼起:

- (void)invocationOperation {
    
    NSInvocationOperation *invocationPeration = [[NSInvocationOperation alloc] initWithTarget:self
                                                                                     selector:@selector(runTheOperation)
                                                                                       object:nil];
    
    [invocationPeration start];
}

- (void)runTheOperation {
    
    NSLog(@"執行任務, 當前的執行緒為: %@", [NSThread currentThread]);
}
複製程式碼
2017-08-06 00:23:58.611 NSOperation-Example[961:42623] 執行任務, 當前的執行緒為: <NSThread: 0x608000066a00>{number = 1, name = main}
複製程式碼

在結果裡, 我們可以看到在沒有使用NSOperationQueue的時候, 是在主執行緒中執行, 並沒有開啟新執行緒.

NSBlockOperation

- (void)blockOperation {
    
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        
        NSLog(@"執行任務, 當前的執行緒為: %@", [NSThread currentThread]);
    }];
    
    [blockOperation start];
}
複製程式碼
2017-08-06 00:26:54.808 NSOperation-Example[1002:47303] 執行任務, 當前的執行緒為: <NSThread: 0x60800006c340>{number = 1, name = main}
複製程式碼

在結果中, 我們看到使用NSBlockOperation也是在主執行緒中執行任務, 並沒有開啟新執行緒.

但是在NSBlockOperation中, 我們還看到了另外一個方法, 這個方法是用來幹嘛的呢? 來看看程式碼吧:

- (void)blockOperation {
    
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        
        NSLog(@"執行任務, 當前的執行緒為: %@", [NSThread currentThread]);
    }];
    
    [blockOperation addExecutionBlock:^{
        
        NSLog(@"執行第二個任務, 當前的執行緒為: %@", [NSThread currentThread]);
    }];

    [blockOperation addExecutionBlock:^{
        
        NSLog(@"執行第三個任務, 當前的執行緒為: %@", [NSThread currentThread]);
    }];

    [blockOperation addExecutionBlock:^{
        
        NSLog(@"執行第四個任務, 當前的執行緒為: %@", [NSThread currentThread]);
    }];

    [blockOperation start];
}
複製程式碼
2017-08-06 00:30:10.238 NSOperation-Example[1043:51425] 執行任務, 當前的執行緒為: <NSThread: 0x60000007bac0>{number = 1, name = main}
2017-08-06 00:30:10.238 NSOperation-Example[1043:51592] 執行第四個任務, 當前的執行緒為: <NSThread: 0x608000267380>{number = 4, name = (null)}
2017-08-06 00:30:10.238 NSOperation-Example[1043:51609] 執行第二個任務, 當前的執行緒為: <NSThread: 0x600000266c40>{number = 3, name = (null)}
2017-08-06 00:30:10.238 NSOperation-Example[1043:51594] 執行第三個任務, 當前的執行緒為: <NSThread: 0x608000267200>{number = 5, name = (null)}
複製程式碼

從列印的結果, 我們可以看出, 這個方法是可以新增額外的任務, 並且在子執行緒同步執行.

自定義NSOperation子類

這裡, 我們建立一個繼承於NSOperation的子類, 暫時想不到有什麼好的場景, 這裡我們簡單寫寫就好了.

首先我們建立一個繼承於NSOperation的子類, 並重寫了- (void)main;方法:

#import "CLOperation.h"

@implementation CLOperation

- (void)main {
    
    for (NSInteger i = 0; i < 5; i++) {
        
        NSLog(@"執行了第%zd次任務, 當前執行緒為: %@", i, [NSThread currentThread]);
    }
}

@end
複製程式碼

然後回到Controller, 執行一番:

- (void)customOperation {
    
    CLOperation *clOperation = [[CLOperation alloc] init];
    
    [clOperation start];
}
複製程式碼
2017-08-06 00:37:32.223 NSOperation-Example[1123:59243] 執行了第0次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.223 NSOperation-Example[1123:59243] 執行了第1次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.224 NSOperation-Example[1123:59243] 執行了第2次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.224 NSOperation-Example[1123:59243] 執行了第3次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.224 NSOperation-Example[1123:59243] 執行了第4次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
複製程式碼

看到輸出的結果, 也是在意料之內, 也是在主執行緒中執行, 並沒有開啟新執行緒.


總結

這一章, 我們就簡單的介紹一下NSOperation, 並且熟悉一下基本的操作, 回頭我們再把NSOperationNSOperationQueue的配合使用補全.


工程地址

專案地址: https://github.com/CainRun/iOS-Project-Example/tree/master/NSOperation-Example


最後

碼字很費腦, 看官賞點飯錢可好
微信
支付寶

相關文章