NSOperation
NSOperation是GCD面向对象的封装, 它有更多的特性.
文档中说NSOperation是一个抽象类, 不要直接使用它,使用它的子类或定义一个继承它的类.它的子类有 NSInvocationOperation 和NSBlockOperation, 貌似swift中没有NSInvocationOperation类, 我们就只管NSBlockOperation了.
1. NSBlockOperation和NSOperationQueue的使用
import UIKit
class ViewController: UIViewController {
var queue: NSOperationQueue!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.queue = NSOperationQueue()
// 设置线程池最大线程数
queue.maxConcurrentOperationCount = 5
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func startAction(sender: AnyObject) {
let downloadOP = NSBlockOperation { () -> Void in
print("下载小说, \(NSThread.currentThread())")
}
let analysisOP = NSBlockOperation { () -> Void in
print("分析目录结构, \(NSThread.currentThread())")
}
let sortOP = NSBlockOperation { () -> Void in
print("章节排序, \(NSThread.currentThread())")
// 主线程上更新UI
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
print("显示小说, \(NSThread.currentThread())")
})
}
// analysisOP依赖downloadOP,即下载完成后才分析目录结构
analysisOP.addDependency(downloadOP)
sortOP.addDependency(analysisOP)
self.queue.addOperation(downloadOP)
self.queue.addOperation(analysisOP)
self.queue.addOperation(sortOP)
}
}
这里我们创建一个NSOperationQueue, 看名字就知道是一个队列了, 我们简单的把它当一个线程池就行了,maxConcurrentOperationCount可以设置它的线程池中的最大线程数目.
NSBlockOperation实例后要添加到queue中才会执行.我们可以通过addDependency设置不同NSBlockOperation之间的依赖关系,以便控制线程的执行顺序. 更新UI的操作要放到主队列中–NSOperationQueue.mainQueue().
运行程序,我们点击按钮:
下载小说, <NSThread: 0x7f8383db13c0>{number = 2, name = (null)}
分析目录结构, <NSThread: 0x7f8383db13c0>{number = 2, name = (null)}
章节排序, <NSThread: 0x7f8383db13c0>{number = 2, name = (null)}
显示小说, <NSThread: 0x7f8383d04a80>{number = 1, name = main}
通过线程的number我们可以知道 下载小说, 分析目录结构, 章节排序实在新开的线程中运行的, 而显示小说是在主线程中运行的.
2. NSOperationQueue的定义
我们查看NSOperationQueue的定义:
@available(iOS 2.0, *)
public class NSOperationQueue : NSObject {
// 添加NSOperation
public func addOperation(op: NSOperation)
@available(iOS 4.0, *)
public func addOperations(ops: [NSOperation], waitUntilFinished wait: Bool)
@available(iOS 4.0, *)
public func addOperationWithBlock(block: () -> Void)
// 获取所有NSOperation
public var operations: [NSOperation] { get }
// 获取NSOperation的数目
@available(iOS 4.0, *)
public var operationCount: Int { get }
// 最大并发线程数
public var maxConcurrentOperationCount: Int
// 是否挂起(暂停)
public var suspended: Bool
// NSOperationQueue的名字
@available(iOS 4.0, *)
public var name: String?
// 服务质量, 级别越高,获得的资源越多
@available(iOS 8.0, *)
public var qualityOfService: NSQualityOfService
@available(iOS 8.0, *)
unowned(unsafe) public var underlyingQueue: dispatch_queue_t? /* actually retain */
// 取消queue的所有操作
public func cancelAllOperations()
// 阻塞当前线程,等待queue的所有操作执行完毕, 所以不要在主线程中调用
public func waitUntilAllOperationsAreFinished()
// 获取当前队列
@available(iOS 4.0, *)
public class func currentQueue() -> NSOperationQueue?
// 获取主队列
@available(iOS 4.0, *)
public class func mainQueue() -> NSOperationQueue
}
3. NSOperation的定义
我们查看NSOperation的定义:
@available(iOS 2.0, *)
public class NSOperation : NSObject {
// 开始任务
public func start()
public func main()
// 操作是否取消
public var cancelled: Bool { get }
// 取消任务
public func cancel()
// 任务是否正在执行
public var executing: Bool { get }
// 任务是否执行完成
public var finished: Bool { get }
// 是否并发,已经过时了, 使用下面的asynchronous
public var concurrent: Bool { get }
@available(iOS 7.0, *)
public var asynchronous: Bool { get }
// 是否已经准备好
public var ready: Bool { get }
// 添加删除依赖
public func addDependency(op: NSOperation)
public func removeDependency(op: NSOperation)
// 获得所有的依赖NSOperation
public var dependencies: [NSOperation] { get }
// 队列优先级
public var queuePriority: NSOperationQueuePriority
// 完成回调
@available(iOS 4.0, *)
public var completionBlock: (() -> Void)?
// 等待完成
@available(iOS 4.0, *)
public func waitUntilFinished()
// 线程优先级
@available(iOS, introduced=4.0, deprecated=8.0)
public var threadPriority: Double
// 服务质量
@available(iOS 8.0, *)
public var qualityOfService: NSQualityOfService
// 名字
@available(iOS 8.0, *)
public var name: String?
}
4. 完整代码
同第一部分