ios - 在 Swift 3 中使用操作类覆盖默认值

标签 ios swift swift3 nsoperation

作为从 2.2 的转换过程的一部分,我试图用 Swift 3 中的 Operation 类覆盖一些值,但我遇到了覆盖类属性的问题。

这是在 Swift 2.2 中正常工作的代码的简化版本:

class ViewController: UIViewController {
    lazy var operationQueue: NSOperationQueue = {
        let queue = NSOperationQueue()
        queue.maxConcurrentOperationCount = 1

        return queue
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        callOperation()
    }

    func callOperation() {
        var error: NSError?

        let words = ["A", "B"]

        words.forEach { word in
            let operation = TestOperation(text: word)
            operation.completionBlock = {
                error = operation.error
            }
            operationQueue.addOperation(operation)
        }

        operationQueue.addOperationWithBlock { 
            if error == nil {
                print("No errors")
            } else {
                print(error?.localizedDescription)
            }
        }
    }
}

class TestOperation: NSOperation {
    private(set) var error: NSError?

    private var text: String?

    private var isExecuting: Bool = false
    private var isFinished: Bool = false

    override var asynchronous: Bool {
        return true
    }

    override var executing: Bool {
        get {
            return isExecuting
        }
        set {
            willChangeValueForKey("isExecuting")
            isExecuting = newValue
            didChangeValueForKey("isExecuting")
        }
    }

    override var finished: Bool {
        get {
            return isFinished
        }
        set {
            willChangeValueForKey("isFinished")
            isFinished = newValue
            didChangeValueForKey("isFinished")
        }
    }

    init(text: String) {
        self.text = text

        super.init()
    }

    override func start() {
        if cancelled {
            finished = true

            return
        }

        executing = true

        func completeOperation() {
            finished = true
            executing = false
        }

        let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(1.0 * Double(NSEC_PER_SEC)))
        dispatch_after(dispatchTime, dispatch_get_main_queue(), {
            print(self.text)
            completeOperation()
        })

    }
}

运行它会产生:

A
B 
No errors

将其转换为 Swift 3.0 后,我得到以下结果,主要问题是围绕带有注释标记的变量:

class ViewController: UIViewController {
    lazy var operationQueue: OperationQueue = {
        let queue = NSOperationQueue()
        queue.maxConcurrentOperationCount = 1

        return queue
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        callOperation()
    }

    func callOperation() {
        var error: NSError?

        let words = ["A", "B"]

        words.forEach { word in
            let operation = TestOperation(text: word)
            operation.completionBlock = {
                error = operation.error
            }
            operationQueue.addOperation(operation)
        }

        operationQueue.addOperationWithBlock {
            if error == nil {
                print("No errors")
            } else {
                print(error?.localizedDescription)
            }
        }
    }
}

class TestOperation: Operation {
    private(set) var error: NSError?

    private var text: String?

//    private var executing: Bool = false // Overriding var must be as accessible as its enclosing type
//    private var finished: Bool = false // Overriding var must be as accessible as its enclosing type

//    var executing: Bool = false // Cannot override a stored property
//    var finished: Bool = false // Cannot override a stored property

    override var executing: Bool = false // Cannot override a stored property
    override var finished: Bool = false // Cannot override a stored property

    override var isAsynchronous: Bool {
        return true
    }

    override var isExecuting: Bool {
        get {
            return executing
        }
        set {
            willChangeValue(forKey: "executing")
            executing = newValue
            didChangeValue(forKey: "executing")
        }
    }

    override var isFinished: Bool {
        get {
            return finished
        }
        set {
            willChangeValue(forKey: "finished")
            finished = newValue
            didChangeValue(forKey: "finished")
        }
    }

    init(text: String) {
        self.text = text

        super.init()
    }

    override func start() {
        if isCancelled {
            isFinished = true

            return
        }

        isExecuting = true

        func completeOperation() {
            isFinished = true
            isExecuting = false
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            print(self.text)
            completeOperation()
        }
    }
}

如果我用其他东西(myFinished、myExecuting)替换完成/执行变量并进行相应更新,我可以运行该应用程序,但我只得到以下内容:

A

这不允许操作正确完成,因此后续操作永远不会运行。

最佳答案

事实证明,我需要在私有(private)变量前加上一个 _ 以便编译器接受它们。

注意事项已用评论突出显示。

下面是 Swift 3 的工作代码:

import UIKit

class ViewController: UIViewController {
    lazy var operationQueue: OperationQueue = {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1

        return queue
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        callOperation()
    }

    func callOperation() {
        var error: NSError?

        let words = ["A", "B"]

        words.forEach { word in
            let operation = TestOperation(text: word)
            operation.completionBlock = {
                error = operation.error
            }
            operationQueue.addOperation(operation)
        }

        operationQueue.addOperation {
            if error == nil {
                print("No errors")
            } else {
                print(error?.localizedDescription)
            }
        }
    }
}

class TestOperation: Operation {
    private(set) var error: NSError?

    private var text: String?

    private var _executing: Bool = false // Notice the _ before the name
    private var _finished: Bool = false // Notice the _ before the name

    override var isAsynchronous: Bool {
        return true
    }

    override var isExecuting: Bool {
        get {
            return _executing
        }
        set {
            willChangeValue(forKey: "isExecuting") // This must match the overriden variable
            _executing = newValue
            didChangeValue(forKey: "isExecuting") // This must match the overriden variable
        }
    }

    override var isFinished: Bool {
        get {
            return _finished
        }
        set {
            willChangeValue(forKey: "isFinished") // This must match the overriden variable
            _finished = newValue
            didChangeValue(forKey: "isFinished") // This must match the overriden variable
        }
    }

    init(text: String) {
        self.text = text

        super.init()
    }

    override func start() {
        if isCancelled {
            isFinished = true

            return
        }

        isExecuting = true

        func completeOperation() {
            isFinished = true
            isExecuting = false
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            print(self.text)
            completeOperation()
        }
    }
}

现在运行时会产生以下内容:

A
B
No errors

关于ios - 在 Swift 3 中使用操作类覆盖默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40309950/

相关文章:

ios - 在 AFNetworking 运行时更改 SSL 固定模式

html - 如何更改和添加适用于 iOS 的 GDPRconsentform.html 文件

ios - Swift 错误 : "Cannot find interface declaration for ' SKScene', 的父类(super class)”

ios - 搜索栏在 swift 3 中不起作用。无法将类型 (_) -> Bool 的值转换为预期的参数类型 NSPredicate

ios - Swift 3 - 调整字体大小以适合宽度,多行

ios - 自动布局中的相对中心

ios - 如何在 iOS 中强制 UISearchBar 文本为大写

ios - 以编程方式将 UIButton 置于 Superview 类的中心(Swift 3)

ios - 相当于在 Swift Combine 中使用 @Published 的计算属性?

ios - JSONDecoder无法解码Array但可以解码String