轉自: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");
}