如何使用bind(_:to:withKeyPath:options :)使两个属性同步?

时间:2019-03-03 05:21:40

标签: swift cocoa-bindings appkit

我想使两个属性与Cocoa绑定保持同步。

在我的代码中,您可以看到我有两个类:Hello world!puts("Hello world!");。我希望保持AB实例中的message值同步,以便一个实例中的更改反映在另一个实例中。我正在尝试使用A非正式协议的B方法。我在macOS上使用Swift 4.2。

bind(_:to:withKeyPath:options:)

在我称为bind NSKeyValueBindingCreation的行中出现编译错误。我得到的建议是用import Cocoa class A: NSObject { @objc dynamic var message = "" } class B: NSObject { @objc dynamic var message = "" init(_ a: A) { super.init() self.bind(#keyPath(message), to: a, withKeyPath: \.message, options: nil) // compile error } } 包装第一个参数。应用完之后,我得到第三个参数的错误cannot convert value of type 'String' to expected argument type 'NSBindingName'

我在做什么错了?

1 个答案:

答案 0 :(得分:0)

我在操场上做了下面的例子。我使用了Counter类,而不是A和B类,因为它更具描述性且更易于理解。

import Cocoa

class Counter: NSObject {
    // Number we want to bind
    @objc dynamic var number: Int

    override init() {
        number = 0
        super.init()
    }
}

// Create two counters and bind the number of the second counter to the number of the first counter
let firstCounter = Counter()
let secondCounter = Counter()

// You can do this in the constructor. This is for illustration purposes.
firstCounter.bind(NSBindingName(rawValue: #keyPath(Counter.number)), to: secondCounter, withKeyPath: #keyPath(Counter.number), options: nil)
secondCounter.bind(NSBindingName(rawValue: #keyPath(Counter.number)), to: firstCounter, withKeyPath: #keyPath(Counter.number), options: nil)

secondCounter.number = 10
firstCounter.number // Outputs 10
secondCounter.number // Outputs 10
firstCounter.number = 60
firstCounter.number // Outputs 60
secondCounter.number // Outputs 60

通常,绑定用于绑定接口和控制器之间,控制器对象之间或控制器对象与模型对象之间的值。它们旨在删除界面和数据模型之间的粘合代码。

如果只想使自己的对象之间的值保持同步,则建议您改用键值观察。它具有更多的好处,并且更容易。虽然NSView和NSViewController为您管理绑定,但是您必须取消绑定自己的对象,然后再释放它们,因为绑定对象对其他对象的引用很弱。使用KVO可以更优雅地处理此问题。

看看WWDC2017 Session 212 - What's New in Foundation。它显示了如何在现代应用程序中使用关键路径和KVO。