IOS開發之NSOperation【轉】

轉自:https://www.cnblogs.com/junior-ios/p/4694557.html

NSOperation 抽象類

  • NSOperation 是一個抽象類,不能直接使用
  • 抽象類的用處是定義子類共有的屬性和方法
  • 在蘋果的頭文件中,有些抽象類和子類的定義是在同一個頭文件中的
  • 子類:
    • NSInvocationOperation (調用)
    • NSBlockOperation (塊)
  • NSOperationQueue 隊列

已經學習過的抽象類

  • UIGestureRecognizer
  • CAAnimation
  • CAPropertyAnimation

基本演練

NSInvocationOperation

start

  • start 方法 會在當前線程執行 @selector 方法
- (void)opDemo1 {
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"Invocation"];

    // start方法 會在當前線程執行 @selector 方法
    [op start];
}

- (void)downloadImage:(id)obj {

    NSLog(@"%@ %@", [NSThread currentThread], obj);
}

添加到隊列

  • 將操作添加到隊列,會異步執行 selector 方法
- (void)opDemo2 {
    NSOperationQueue *q = [[NSOperationQueue alloc] init];

    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"queue"];

    [q addOperation:op];
}

添加多個操作

- (void)opDemo3 {
    NSOperationQueue *q = [[NSOperationQueue alloc] init];

    for (int i = 0; i < 10; ++i) {
        NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@(i)];

        [q addOperation:op];
    }
}

執行效果:會開啓多條線程,而且不是順序執行。與GCD中併發隊列&異步執行效果一樣!

結論,在 NSOperation 中:

  • 操作 -> 異步執行的任務
  • 隊列 -> 全局隊列

NSBlockOperation

- (void)opDemo4 {
    NSOperationQueue *q = [[NSOperationQueue alloc] init];

    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@", [NSThread currentThread]);
    }];

    [q addOperation:op];
}

使用 block 來定義操作,所有的代碼寫在一起,更簡單,便於維護!

更簡單的,直接添加 Block

- (void)opDemo5 {
    NSOperationQueue *q = [[NSOperationQueue alloc] init];

    for (int i = 0; i < 10; ++i) {
        [q addOperationWithBlock:^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        }];
    }
}

向隊列中添加不同的操作

- (void)opDemo5 {
    NSOperationQueue *q = [[NSOperationQueue alloc] init];

    for (int i = 0; i < 10; ++i) {
        [q addOperationWithBlock:^{
            NSLog(@"%@ %d", [NSThread currentThread], i);
        }];
    }

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block %@", [NSThread currentThread]);
    }];
    [q addOperation:op1];

    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"invocation"];
    [q addOperation:op2];
}
  • 可以向 NSOperationQueue 中添加任意 NSOperation 的子類

線程間通訊

- (void)opDemo6 {
    NSOperationQueue *q = [[NSOperationQueue alloc] init];

    [q addOperationWithBlock:^{
        NSLog(@"耗時操作 %@", [NSThread currentThread]);

        // 主線程更新 UI
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"更新 UI %@", [NSThread currentThread]);
        }];
    }];
}

高級演練

全局隊列

/// 全局操作隊列,統一管理所有的異步操作
@property (nonatomic, strong) NSOperationQueue *queue;

- (NSOperationQueue *)queue {
    if (_queue == nil) {
        _queue = [[NSOperationQueue alloc] init];
    }
    return _queue;
}

最大併發操作數

/// MARK: - 最大併發操作數
- (void)opDemo1 {

    // 設置同時併發操作數
    self.queue.maxConcurrentOperationCount = 2;

    NSLog(@"start");

    for (int i = 0; i < 10; ++i) {
        NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
            [NSThread sleepForTimeInterval:1.0];
            NSLog(@"%@ %d", [NSThread currentThread], i);
        }];

        [self.queue addOperation:op];
    }
}

暫停 & 繼續

/// MARK: - 暫停 & 繼續
- (IBAction)pauseAndResume {

    if (self.queue.operationCount == 0) {
        NSLog(@"沒有操作");
        return;
    }

    // 暫停或者繼續
    self.queue.suspended = !self.queue.isSuspended;

    if (self.queue.isSuspended) {
        NSLog(@"暫停 %tu", self.queue.operationCount);
    } else {
        NSLog(@"繼續 %tu", self.queue.operationCount);
    }
}
  • 隊列掛起,當前沒有完成的操作,是包含在隊列的操作數中的
  • 隊列掛起,不會影響已經執行操作的執行狀態
  • 對列一旦被掛起,再添加的操作不會被調度

取消全部操作

/// MARK: - 取消所有操作
- (IBAction)cancelAll {
    if (self.queue.operationCount == 0) {
        NSLog(@"沒有操作");
        return;
    }

    // 取消對列中的所有操作,同樣不會影響到正在執行中的操作!
    [self.queue cancelAllOperations];

    NSLog(@"取消全部操作 %tu", self.queue.operationCount);
}
  • 取消隊列中所有的操作
  • 不會取消正在執行中的操作
  • 不會影響隊列的掛起狀態

依賴關係

/// MARK: - 依賴關係
- (void)dependency {

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"登錄 %@", [NSThread currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"付費 %@", [NSThread currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下載 %@", [NSThread currentThread]);
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"通知用戶 %@", [NSThread currentThread]);
    }];

    [op2 addDependency:op1];
    [op3 addDependency:op2];
    [op4 addDependency:op3];
    // 注意不要循環依賴
//    [op1 addDependency:op4];

    [self.queue addOperations:@[op1, op2, op3] waitUntilFinished:NO];
    [[NSOperationQueue mainQueue] addOperation:op4];

    NSLog(@"come here");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章