Как синхронизировать два свойства с помощью bind (_: to: withKeyPath: options :)? - PullRequest
0 голосов
/ 03 марта 2019

Я хочу синхронизировать два свойства с привязками Какао.

В моем коде вы можете видеть, что у меня есть два класса: A и B.Я хочу, чтобы значения message в экземплярах A и B были синхронизированы, чтобы изменение одного отражалось на другом.Я пытаюсь использовать метод bind(_:to:withKeyPath:options:) неофициального протокола NSKeyValueBindingCreation.Я использую Swift 4.2 на macOS.

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

Я получаю ошибку компиляции в строке, где я вызываю bind: cannot convert value of type 'String' to expected argument type 'NSBindingName'.Я получаю предложение обернуть первый параметр с NSBindingName(rawValue: ).После этого я получаю ошибку type of expression is ambiguous without more context для третьего параметра.

Что я делаю не так?

1 Ответ

0 голосов
/ 05 марта 2019

Я сделал следующий пример на детской площадке.Вместо классов A и B я использовал класс Counter, поскольку он более нагляден и проще для понимания.

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

Обычно привязки используются для привязки значений между вашим интерфейсом и контроллером или между объектами контроллера,или между объектом контроллера и объектами вашей модели.Они предназначены для удаления связующего кода между вашим интерфейсом и моделью данных.

Если вы хотите только синхронизировать значения между вашими собственными объектами, я предлагаю вместо этого использовать Key-Value Observing.Это имеет больше преимуществ, и это проще.В то время как NSView и NSViewController управляют привязками для вас, вы должны отсоединить ваши собственные объекты, прежде чем они будут освобождены, потому что объект привязки сохраняет слабую ссылку на другой объект.Это обрабатывается более изящно с KVO.

Взгляните на WWDC2017 Session 212 - Что нового в Foundation .Он показывает, как использовать ключевые пути и KVO в современном приложении.

...