iOS swift Operation Queue

时间:2018-02-03 01:48:23

标签: swift concurrency nsoperationqueue nsoperation operation

我在iOS应用程序上工作,我正在使用OperationQueue。我创建了2个操作。 Operation2取决于Operation1.Operation2的完成,需要等到操作1完成后才运行。如果操作1未运行,则应立即开始操作2.

它没有按预期工作,所以我在游乐场测试

    class MyManager {

        var operationQueue: OperationQueue?

        var operation1: MyOperation? = nil
        var operation2: MyOperation? = nil

        typealias completion = (_ serverError: String?) -> Void

        func talkWithServer(completion: completion?) {

            completion?("competed!")
        }

        func doOperation1() {

            cancelProcess()
            setup()

            guard let operation1 = self.operation1 else { return }
            operation1.codeToRun = {
                print("operation1 started")
                self.talkWithServer(completion: { (completion) in
                    print("operation1 completed")
                    operation1.markAsFinished()
                })
            }
            operationQueue?.addOperation(operation1)

        }


        func doOperation2() {
           self.operation2 = MyOperation()

            guard let operation2 = self.operation2 else { return }



            operation2.codeToRun = {
                print("operation2 started")
                self.talkWithServer(completion: { (completion) in
                    print("operation2 completed")
                    operation2.markAsFinished()
                })
            }

if let operation1 = self.operation1 {
            if operation1.isExecuting {
                operation2.addDependency(operation1)
                operation1.completionBlock = {
                    print("operation1.completionBlock")
                    self.operationQueue?.addOperation(operation2)
                }
            }
            } else  {
                operationQueue?.addOperation(operation2)
            }

        }


        func cancelProcess() {
            print("cancelAllOperations")
            operationQueue?.cancelAllOperations()
        }

        func setup() {
            print("setup Called")
            operationQueue?.cancelAllOperations()
            operationQueue = OperationQueue()
            operation1 = MyOperation()
            operation2 = MyOperation()
        }
    }


    class MyOperation: Operation {
        var codeToRun: (()->Void)?

        var _executing = false
        var _finished = false

        override internal(set) var isExecuting: Bool {
            get {
                return _executing
            }
            set {
                _executing = newValue

            }
        }

        override internal(set) var isFinished: Bool {
            get {
                return _finished
            }
            set {
                _finished = newValue
            }
        }

        override var isAsynchronous: Bool {
            return true
        }

        override func start() {
            isExecuting = true
            isFinished = false
            if let closure = self.codeToRun {
                closure()
            }
        }

        func markAsFinished() {
            self.isExecuting = false
            self.isFinished = true
            completionBlock?()
        }
    }

    let manager = MyManager()

    manager.doOperation1()
    manager.doOperation2()

我收到了结果

cancelAllOperations
setup Called
operation1 started
operation1 completed
operation1.completionBlock

预期

cancelAllOperations
setup Called
operation1 started
operation1 completed
operation1.completionBlock
operation2 started
operation2 completed

我在这里错过了什么吗?

3 个答案:

答案 0 :(得分:1)

我一直在看你的代码。我找到了一些东西:

第一

manager.doOperation1()
manager.doOperation2()

这并不意味着operation2在operation1完成后运行,如果你想这样做,你可以为operation1添加一个完成闭包。

第二

致电

doOperation2()

在这个函数中似乎代码从未执行过:

guard let operation2 = self.operation2 else { return }

毕竟

您似乎想要创建自己的车轮。我建议你学习一些关于GCD的知识,你可以在这里找到资源:

Grand Central Dispatch Crash Course for Swift 3

Grand Central Dispatch Tutorial for Swift 3: Part 1/2

答案 1 :(得分:0)

有几件事:

实现:

  • KVOisExecuting
  • 实施isFinished
  • 修复doOperation2
  • 设置依赖项后,operation2即使在operation1完成之前已添加到队列中,也无法启动。
  • MyOperation
  • 中检查isCancelled

下面不是实现doOperation2的理想方法,但会从代码中消除一些混乱。我将根据下面提到的设计部分留给你实现整个事情。

func doOperation2() {

    self.operation2 = MyOperation()

    guard let operation2 = self.operation2 else {
        return
    }

    operation2.codeToRun = {
        print("operation2 started")

        self.talkWithServer(completion: { (completion) in
            print("operation2 completed")
        })
    }

    operationQueue?.addOperation(operation2)
}

设计

  • 在您的实施中,MyOperation似乎是通用的,您似乎在您称之为的地方进行大部分实际工作
  • 修改MyOperation以完成实际工作。
  • 呼叫网站应该简单
  • 示例FetchData()是一个操作,ParseData()是另一个操作。
  • 因此,操作包含业务逻辑。
  • 在呼叫站点,您只需添加依赖项。

答案 2 :(得分:0)

您需要做的就是添加对依赖操作的依赖。

        let queue = OperationQueue()

        let operation1 = BlockOperation(block: { [weak self] in
            self?.doOperation1()
        })

        let operation2 = BlockOperation(block: { [weak self] in
            self?.doOperation2()
        })

        operation1.addDependency(operation2) // THIS IS THE KEY CODE IN YOUR CASE

        queue.addOperation(operation1)
        queue.addOperation(operation2)

希望这可以帮助您解决依赖性问题。