一、与GCD比较
* GCD是底层的C语言构成的API,而NSOperationQueue以及相关对象是基于GCD的Objective-C对象的封装,作为一个对象,NSOperationQueue为我们提供了更多的选择
* NSOperationQueue任务可以很方便的取消(也只能取消未执行的任务),而GCD没法停止已经加入队列的任务(其实是有的,但需要许多复杂的代码)
* 不像GCD那样的是按FIFO顺序来执行的,NSOperation能够方便地通过依赖关系设置操作执行顺序,可以控制任务在特定的任务执行完后才执行;而GCD要实现这个功能的话,就需要通过barrier或者group来控制执行顺便,如果依赖关系复杂的话,代码逻辑就非常复杂了
* NSOperation支持KVO(Key-Value Observing),可以方便的监听任务的状态(完成、执行中、取消等等状态)
* NSOperation可以设置同一个队列中任务的优先级,能够使同一个并行队列中的任务区分先后地执行,而在GCD中,我们只能区分不同任务队列的优先级,如果要区分block任务的优先级,也需要大量的复杂代码
* 还可以通过自定义NSOperation,封装任务逻辑,提高整个代码的复用度
二、说明
NSOperation相当于是NSOperationQueue中一个操作任务。NSOperation本身是一个抽象类,不能直接使用。我们可以使用系统提供的子类NSInvocationOperation(swift不支持) 和NSBlockOperation
,或者自己实现NSOperation子类的方式来执行操作任务。NSOperation对象都是通过调用start方法来开始执行任务。
三、分类
- NSInvocationOperation
swift 不支持 - NSBlockOperation
// 创建NSBlockOperation对象
self.blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation1 thread:%@",[NSThread currentThread]);
}];
[self.blockOperation addExecutionBlock:^{
NSLog(@"blockOperation2 thread:%@",[NSThread currentThread]);
}];
[self.blockOperation addExecutionBlock:^{
NSLog(@"blockOperation3 thread:%@",[NSThread currentThread]);
}];
[self.blockOperation start];
NSLog(@"after blockOperation");
- completionBlock
[self.invocationOperation setCompletionBlock:^{
NSLog(@"invocationOperation completion");
}];
[self.blockOperation setCompletionBlock:^{
NSLog(@"blockOperation completion");
}];
- NSOperationQueue
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let block = BlockOperation {
print("1")
}
block.completionBlock = {
print("end")
}
block.addExecutionBlock {
print("2")
}
block.addExecutionBlock {
print("3")
}
block.addExecutionBlock {
print("4")
}
block.addExecutionBlock {
print("5")
}
block.addExecutionBlock {
print("6")
}
let queue = OperationQueue()
queue.addOperation(block)
queue .addOperation {
print("7")
}
}
四、添加依赖
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let block1 = BlockOperation {
print("1")
}
let block2 = BlockOperation {
print("2")
}
let block3 = BlockOperation {
print("3")
}
let block4 = BlockOperation {
print("4")
}
let block5 = BlockOperation {
print("5")
}
block2.addDependency(block1)
block3.addDependency(block2)
block4.addDependency(block3)
block5.addDependency(block4)
block1.start()
block2.start()
block3.start()
block4.start()
block5.start()
}
五、取消操作
[self.blockOperation cancel];
[self.invocationOperation cancel];
[self.queue cancelAllOperations];
六、设置优先级
[self.blockOperation setQueuePriority:NSOperationQueuePriorityHigh];
[self.invocationOperation setQueuePriority:NSOperationQueuePriorityLow];
七、暂停和继续
[self.queue setSuspended:YES]; //暂停
[self.queue setSuspended:NO]; //继续
八、设置最大并发数
可以通过maxConcurrentOperationCount属性设置最大并发数,该值默认为-1,由系统调度。当设置为1的时候相当于是一个同步执行的操作队列。
九、等待 NSOperation 执行完成
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let block1 = BlockOperation {
print("1")
}
print("start")
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 10) {
block1.start()
}
// 当前线程被阻塞
block1.waitUntilFinished()
print("end")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let block1 = BlockOperation {
print("1")
}
let queue = OperationQueue()
queue.addOperation(block1)
print("start")
queue.waitUntilAllOperationsAreFinished()
print("end")
}
十、监听属性
- isExecuting 代表任务正在执行中
- isFinished 代表任务已经执行完成,被取消也算执行完成
注:该状态关系到依赖其的操作任务,只有在其isFinished状态为YES的时候,依赖其的操作任务才能开始执行,操作队列也是根据这个状态来决定是否将操作任务从队列中移除 - isCancelled 代表任务已经取消执行
- isAsynchronous 代表任务是并发还是同步执行
注:当操作任务加入到操作队列后,会忽略该属性 - isReady 代表任务是否已经准备执行
注:当其依赖的操作任务都执行完时,改状态才会是YES
十一、自定义NSOperation
- 自定义同步NSOperation
- 自定义并发NSOperation
网友评论