Operation和OperationQueue可以在不关心线程的情况下完成多线程编程,只需要添加任务和创建队列,线程调度由系统来完成。
我们来看看Operation的头文件:
@available(iOS 2.0, *)
open class Operation : NSObject {
open func start()
open func main()
open var isCancelled: Bool { get }
open func cancel()
open var isExecuting: Bool { get }
open var isFinished: Bool { get }
open var isConcurrent: Bool { get }
@available(iOS 7.0, *)
open var isAsynchronous: Bool { get }
open var isReady: Bool { get }
open func addDependency(_ op: Operation)
open func removeDependency(_ op: Operation)
open var dependencies: [Operation] { get }
open var queuePriority: Operation.QueuePriority
@available(iOS 4.0, *)
open var completionBlock: (() -> Swift.Void)?
@available(iOS 4.0, *)
open func waitUntilFinished()
@available(iOS, introduced: 4.0, deprecated: 8.0, message: "Not supported")
open var threadPriority: Double
@available(iOS 8.0, *)
open var qualityOfService: QualityOfService
@available(iOS 8.0, *)
open var name: String?
}
extension Operation {
public enum QueuePriority : Int {
case veryLow
case low
case normal
case high
case veryHigh
}
}
@available(iOS 4.0, *)
open class BlockOperation : Operation {
public convenience init(block: @escaping () -> Swift.Void)
open func addExecutionBlock(_ block: @escaping () -> Swift.Void)
open var executionBlocks: [() -> Swift.Void] { get }
}
extension NSExceptionName {
@available(iOS 2.0, *)
public static let invocationOperationVoidResultException: NSExceptionName
@available(iOS 2.0, *)
public static let invocationOperationCancelledException: NSExceptionName
}
PS:带{ get }的是只读属性
如你所见,Swift4里已经没有OC的NSInvocationOperation,因为selector在Swift里不太提倡,所以现在只剩下BlockOperation来对应OC的NSBlockOperation。
跟以前一样,Operation是个抽象类不能直接操作,需要用BlockOperation,或者自定义一个继承自Operation的子类。
BlockOperation使用方法像以前一样:
//初始化一个operation
let op = BlockOperation.init {
sleep(UInt32(UInt(2)))
print("线程===\(Thread.current)")
}
for i in 1...10 {
op.addExecutionBlock {
sleep(UInt32(UInt(2)))
print("\(i)线程===\(Thread.current)")
}
}
op.start()
print("op同步执行")
3线程===<NSThread: 0x60800026a7c0>{number = 9, name = (null)}
1线程===<NSThread: 0x60400007b980>{number = 5, name = (null)}
5线程===<NSThread: 0x608000069700>{number = 1, name = main}
4线程===<NSThread: 0x60c00007bc40>{number = 3, name = (null)}
2线程===<NSThread: 0x600000464b00>{number = 7, name = (null)}
6线程===<NSThread: 0x60c00026a780>{number = 6, name = (null)}
线程===<NSThread: 0x60c00026a800>{number = 4, name = (null)}
7线程===<NSThread: 0x60800026a700>{number = 8, name = (null)}
10线程===<NSThread: 0x608000069700>{number = 1, name = main}
9线程===<NSThread: 0x60400007b980>{number = 5, name = (null)}
8线程===<NSThread: 0x60800026a7c0>{number = 9, name = (null)}
op同步执行
可以看到,BlockOperation可以通过addExecutionBlock方法添加多个操作,这些操作连同初始化时传入的操作可以多线程执行,但是不管开启几个线程,BlockOperation还是同步执行,所有的操作都完成以后,才会接着执行下面的print("op同步执行")任务。所以,这基本上没什么用,你几乎不可能需要这样的多线程😀。一般都是要配合OperationQueue来完成多线程操作的。
接着来看看OperationQueue的头文件:
extension OperationQueue {
public class let defaultMaxConcurrentOperationCount: Int
}
@available(iOS 2.0, *)
open class OperationQueue : NSObject {
open func addOperation(_ op: Operation)
@available(iOS 4.0, *)
open func addOperations(_ ops: [Operation], waitUntilFinished wait: Bool)
@available(iOS 4.0, *)
open func addOperation(_ block: @escaping () -> Swift.Void)
open var operations: [Operation] { get }
@available(iOS 4.0, *)
open var operationCount: Int { get }
open var maxConcurrentOperationCount: Int
open var isSuspended: Bool
@available(iOS 4.0, *)
open var name: String?
@available(iOS 8.0, *)
open var qualityOfService: QualityOfService
@available(iOS 8.0, *)
unowned(unsafe) open var underlyingQueue: DispatchQueue?
open func cancelAllOperations()
open func waitUntilAllOperationsAreFinished()
@available(iOS 4.0, *)
open class var current: OperationQueue? { get }
@available(iOS 4.0, *)
open class var main: OperationQueue { get }
}
可以看到,OperationQueue有两个类方法,current来获取当前的队列,main用来获取主队列,UI刷新就是这个队列里完成的。
比如常用的开启一个后台任务,完成以后回到主线程刷新:
OperationQueue.init().addOperation {
//完成耗时操作
sleep(UInt32(UInt(2)))
print("线程====\(Thread.current)")
OperationQueue.main.addOperation({
//完成UI刷新
print("线程====\(Thread.current)")
})
}
不得不说,Swift的确很简化,这里跟GCD有一拼:
DispatchQueue.global().async {
//这里完成耗时任务
DispatchQueue.main.async {
//回到主线程刷新UI
}
}
OperationQueue添加操作的方法有三个:
- addOperation(_ op: Operation):添加一个Operation对象
- addOperations(_ ops: [Operation], waitUntilFinished wait: Bool):添加Operation对象数组,并且设置是否等待任务结束,waitUntilFinished为true是阻塞当前线程直到将添加的操作执行完成,false则不阻塞,说白了就是同步跟异步的控制吧。
- addOperation(_ block: @escaping () -> Swift.Void):直接添加一个操作
网友评论