An operation object is an instance of the NSOperation class (in the Foundation framework) that you use to encapsulate work you want your application to perform. The NSOperation class itself is an abstract base class that must be subclassed in order to do any useful work.
NSOperation本身是一個抽象基類,如果要使用的時候應該先繼承它而不能直接去實例化一個NSOperation。
Foundation framework提供兩個子類,NSInvocationOperation和NSBlockOperation。NSInvocationOperation不需要再繼承才能使用,可以方便我們以現有的方法來初始化一個operation。NSBlockOperation方便我們通過block初始化operation。
NSOperation特征:
NSOperation之間可以建立依賴關系
可以改變operation的優先級
能夠通過取消操作停止operation
有可選的operation block,當主任務完成后
KVO監聽狀態
NSInvocationOperation & NSBlockOperation例子
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.operation = [self taskWithData:@"just test"];
[self.operation start];
NSBlockOperation *blockTest = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"block is comeing");
}];
[blockTest addExecutionBlock:^{
NSLog(@"blocke 2 is coming");
}];
[blockTest addExecutionBlock:^{
NSLog(@"blocke 3 is coming");
}];
[blockTest start];}
- (NSOperation *)taskWithData:(id)data{
NSInvocationOperation *invoTest = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(handleData:) object:data];
return invoTest;
}
- (void)handleData:(id) data
{
NSLog(@"my data");
NSLog(@"%@", data);
}
自定義的NSOperation
至少要實現兩個方法:
- A custom initialization method(初始化的方法)
- main
簡單實現代碼:
@implementation MyOperation
- (instancetype)initWithData:(id) data
{
if (self = [super init]) {
self.myData = data;
[self completeOperation];
}
return self;
}
- (void)main
{
@try {
NSLog(@"my operation is coming");
NSLog(@"%@", _myData);
}
@catch (NSException *exception) {
NSLog(@"%@", exception);
}
@finally {
NSLog(@"finally");
}
}
@end
在ViewController里面實例化
MyOperation *myOperation = [[MyOperation alloc] initWithData:@"my opeation"];
[myOperation start];
并發的NSOperation需要實現以下方法:
- (BOOL)isConcurrent
{
return YES;
}
- (BOOL)isExecuting {
return executing;
}
- (BOOL)isFinished {
return finished;
}
- (void)start{
if([self isCancelled])
{
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;
}
[self willChangeValueForKey:@"isExecuting"];
[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];
}
- (void)completeOperation {
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
Operation中支持KVO的屬性
isCancelled
isConcurrent
isExecuting
isFinished
isReady
dependencies
queuePriority
completionBlock
NSOperationQueue
兩種初始化的方法:
NSOperationQueue *myQueue1 = [[NSOperationQueue alloc] init];
NSOperationQueue *myQueue2 = [NSOperationQueue mainQueue];//mainQueue
[myQueue1 addOperation:myOperation];
[myQueue1 addOperation:self.operation];
[myQueue1 addOperation:blockTest];
- NSOperationQueue有優先級的概念,因此是不支持FIFO的
- NSOperationQueue是并發執行的,但是可以通過maxConcurrentOperationCount來設置并發的數量
NSOperation相對于GCD的優勢
可以取消某個操作。調用cancel方法可以取消操作,但是開始的任務是無法取消的。而GCD是fire and forget模式。
指定操作間的依賴關系,指定特定的任務必須在某個任務完成后執行。
可以通過KVO監控NSOperation對象的屬性。通過KVO就可以在何時結束何時掛起獲得通知,進而做一些處理
指定操作間的優先級。GCD的優先級是針對整個隊列來說的,操作隊列就能比較方便的實現優先級操作
重用NSOperation對象。
參考
- 《Effective Objective-C 2.0》
- 《Concurrency Programming Guide》