NSOperation 简介

常用子类:

NSOperation是一个基类,不应该直接生成NSOperation对象,而是应该用它的子类。

  • NSInvocationOperation
    • 将特定对象的特定方法封装成NSOperation
  • NSBlockOperation
    • 将代码块封装成NSOpreation

示例:

创建NSInvocationOperation

NSString* url = @"http://www.xxx.com";
//以self的downloadImageFromURL:方法作为执行体,创建NSOperation
NSInvocationOperation* operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImageFromURL:) object:url];	 

创建NSBlockOperation

NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
	//执行体
	...
}];

常用状态:

可以通过KVO监听NSOperation的状态

  • isCancelled
  • isAsynchronous
  • isExecuting
  • isFinished
  • isReady

执行任务

创建了一个NSBlockOperation,并且设置好它的block,也就是将要执行的任务。这个任务会在主线程中执行。

调用start方法让NSOperation方法运行起来。start是一个同步方法。

在当前任务状态和依赖关系合适的情况下,启动NSOperation的main方法任务,需要注意缺省实现只是在当前线程运行。如果需要并发执行,子类必须重写这个方法,并且使 - (BOOL)isConcurrent 方法返回YES

let operation = NSBlockOperation { () -> Void in  
	print(NSThread.currentThread())
}
operation.addExecutionBlock { () -> Void in  
	print("execution block1 --(NSThread.currentThread())")
}
operation.start()

默认的NSOperation是同步执行的。简单的看一下NSOperation类的定义会发现它有一个只读属性asynchronous

这意味着如果想要异步执行,就需要自定义NSOperation的子类。或者使用NSOperationQueue

取消任务

如果我们有两次网络请求,第二次请求会用到第一次的数据。如果此时网络情况不好,第一次请求超时了,那么第二次请求也没有必要发送了。当然,用户也有可能人为地取消某个NSOperation。

当某个NSOperation被取消时,我们应该尽可能的清除NSOperation内部的数据并且把cancelled和finished设为true,把executing设为false。

//取消某个NSOperation
operation1.cancel()

//取消某个NSOperationQueue剩余的NSOperation
queue.cencelAllOperations()

获取状态

  • @property(readonly, getter=isCancelled) BOOL cancelled
    • 当前任务状态是否已标记为取消
  • @property(readonly, getter=isExecuting) BOOL executing
    • 当前任务状态是否已标记为取消
  • @property(readonly, getter=isFinished) BOOL finished
    • NSOperation任务是否已结束
  • @property(readonly, getter=isConcurrent) BOOL concurrent
  • @property(readonly, getter=isAsynchronous) BOOL asynchronous
  • @property(readonly, getter=isReady) BOOL ready
    • NSOperation任务是否已结束
  • @property(copy) NSString *name

等待

  • -(void)waitUntilFinished

      NSBlockOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
      	[opA waitUntilFinished]; //opB线程等待直到opA执行结束(正常结束或被取消)
      	[self operate];
      }]; 
    

设置依赖

依然考虑刚刚所说的两次网络请求的例子。因为第二次请求会用到第一次的数据,所以我们要保证发出第二次请求的时候第一个请求已经执行完。但是我们同时还希望利用到NSOperationQueue的并发特性(因为可能不止这两个任务)。

这时候我们可以设置NSOperation之间的依赖关系。语法非常简洁:

operation2.addDependency(operation1)

需要注意的是NSOperation之间的相互依赖会导致死锁

移除依赖:

- (void)removeDependency:(NSOperation *)operation

优先级

GCD中,任务(block)是没有优先级的,而队列具有优先级。和GCD相反,我们一般考虑NSOperation的优先级

NSOperation有一个NSOperationQueuePriority枚举类型的属性queuePriority

typedef enum : NSInteger {
	NSOperationQueuePriorityVeryLow = -8,
	NSOperationQueuePriorityLow = -4,
	NSOperationQueuePriorityNormal = 0,
	NSOperationQueuePriorityHigh = 4,
	NSOperationQueuePriorityVeryHigh = 8
} NSOperationQueuePriority;
posted @ 2016-04-07 17:33  孙焱焱  阅读(438)  评论(0编辑  收藏  举报