NSOperation 和 GCD 都是iOS下多线程编程相关的技术,NSOperation 是在iOS2之后引入的,GCD稍微晚点,它是在iOS4和OS X 10.6之后引入的。因为这两项技术都是用来做多线程相关的工作,所以很多程序员在使用的时候不知道如何选择。这篇文章的主要内容就是介绍如何在这两项技术之间做选择。
在介绍如何选择这两种API之前,我准备先介绍下NSOperation和GCD的主要区别。
主要区别
NSOperation是对GCD的一个封装(因为NSOperation是在GCD之前出现的,所以在GCD出现之前,NSOperation并不是对GCD的封装),以objective-c面向对象的方式提供API,这就意味着,如果你用NSOperation,其实底层还是用的GCD。
GCD是一套C的API,相对底层一点。所以,NSOperation相对效率更低。因为实例化一个NSOperation对象、以及释放一个NSOperation都是需要代价的。
NSOperation的优点
虽然NSOperation是建立在GCD之上的API,但是NSOperation有几个功能是GCD无法提供的。
- Dependencies (依赖)
NSOperation支持依赖,比如说有两个operation A和B,A要在B执行完之后执行,那么可以他们提供一个依赖关系即可。
- Observable
NSOperation和NSOperationQueue有许多属性是可以通过kvo来观察,这样的话你可以实时监测operation和operation queue的状态。
- Pause,Cancel,Resume
operation可以暂停(pause)、唤醒(resumed),以及取消(canceled),GCD就不存在这种控制的API,所以,NSOperation可以更灵活的控制operation的生命周期。
- Control
使用NSOperationQueue还有其他的好处,比如说可以指定同时最大并发数。
如何选择NSOperation和GCD
通常情况下,Apple建议开发者选择高层的API,如果我们遵守这个原则,那么应该选用NSOperation比较好。
选用高层的API有一个好处,就是每次iOS系统的更新,Apple都会调整或者一些framework或者library,从而使系统更加优秀,这样的更新往往会涉及底层的API,所以,如果我们使用的高层的API,就算我们没有改变我们使用的API,我们也可以享受苹果对底层代码的优化带来的好处,如果我们使用的底层的API,那么我们的应用也必须进行相应的升级才能享受这种变化。
基于此是不是就是说完全使用NSOperation,避免使用GCD呢?实际上也不是这样的,我们需要根据实际的情况使用NSOperation或者GCD,亦或者同时使用这两者。
- 什么时候使用NSOperation
NSOperation非常适合封装功能明确的功能块,比如说,你可以用NSOperation的子类封装用户登录的模块。
依赖也是NSOperation中的一个非常有用的特点,当你的功能模块需要一个特定的顺序的时候,那么NSOperation是最好选择。
- 什么时候使用GCD
如果你的需求仅仅是把一个代码块调度到一个串行或者并发的队列里,那么GCD是个好的选择,因为这样不需要创建NSOperation的子类,而且使用GCD相关的代码都在一块,代码的可读性要高。比如下面的代码:
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
// Process Response
...
dispatch_async(dispatch_get_main_queue(), { () -> Void in
// Update User Interface
...
})
})
- NSBlockOperation
开发者不能直接使用NSOperation,也就是必须要使用它的子类。Foundaation框架已经提供了一个可以直接使用的子类NSBlockOperation,使用方式如下:
let operation = NSBlockOperation(block: { () -> Void in
// Do Something
...
})
operationQueue.addOperation(operation)
总结
本文介绍了NSOperation和GCD的区别,在使用的时候尽量使用NSOperation,因为这样可以进行很好的控制。当然,如果是很简单的调度,直接使用GCD是一种更好的选择。