Swift4里的Operation和OperationQueue

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线程==={number = 9, name = (null)}
1线程==={number = 5, name = (null)}
5线程==={number = 1, name = main}
4线程==={number = 3, name = (null)}
2线程==={number = 7, name = (null)}
6线程==={number = 6, name = (null)}
线程==={number = 4, name = (null)}
7线程==={number = 8, name = (null)}
10线程==={number = 1, name = main}
9线程==={number = 5, name = (null)}
8线程==={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添加操作的方法有三个:

  1. addOperation(_ op: Operation):添加一个Operation对象
  2. addOperations(_ ops: [Operation], waitUntilFinished wait: Bool):添加Operation对象数组,并且设置是否等待任务结束,waitUntilFinished为true是阻塞当前线程直到将添加的操作执行完成,false则不阻塞,说白了就是同步跟异步的控制吧。
  3. addOperation(_ block: @escaping () -> Swift.Void):直接添加一个操作

你可能感兴趣的:(Swift4里的Operation和OperationQueue)