美文网首页
Swift4里的Operation和OperationQueue

Swift4里的Operation和OperationQueue

作者: 青山不改 | 来源:发表于2019-03-13 09:36 被阅读0次

    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添加操作的方法有三个:

    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

          本文链接:https://www.haomeiwen.com/subject/jyzmhftx.html