iOS swift Operation Queue

问题描述 投票:1回答:3

我在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

我在这里错过了吗?

swift concurrency nsoperationqueue nsoperation operation
3个回答
1
投票

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

First

manager.doOperation1()
manager.doOperation2()

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

Second

你打电话的时候

doOperation2()

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

guard let operation2 = self.operation2 else { return }

After all

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

Grand Central Dispatch Crash Course for Swift 3

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


0
投票

有几件事:

Implementation:

  • 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)
}

Design:

  • 在你的实现中,MyOperation似乎是通用的,你似乎在你称之为的地方做了大部分真正的工作
  • 修改MyOperation来做真正的工作。
  • 呼叫站点应该很简单
  • 示例FetchData()是一个操作,ParseData()是另一个操作。
  • 因此,操作包含业务逻辑。
  • 在呼叫站点,您只需添加依赖项。

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)

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

© www.soinside.com 2019 - 2024. All rights reserved.