Как реализовать двухстороннее связывание со Swift?
Как реализовать двухстороннее связывание данных с помощью Swift 2.0?
Давайте предположим, что у меня есть следующий класс модели (с использованием couchbase lite):
@objc(Person)
class Person: NSObject{
@NSManaged var firstName: NSString?
@NSManaged var lastName: NSString?
}
И мне нравится связывать свойства с заданным formItemDescriptor следующим образом:
class FormItemDescriptor {
var tag: String?
var value: Any?
}
Как бы я связал FormItemDescriptor.value
собственность на Person.firstName
свойство с помощью двухсторонней привязки?
То есть изменения в модели появляются в форме и наоборот?
1 ответ
Swift не поддерживает привязки из коробки, но вы можете достичь их с помощью таких фреймворков, как ReactiveKit.
Например, когда вы объявляете наблюдаемое свойство, вы можете связать его с другим наблюдаемым свойством.
let numberA: Property<Int>
let numberB: Property<Int>
numberA.bindTo(numberB)
Чтобы сделать двунаправленный, просто свяжите в другом направлении:
numberB.bindTo(numberA)
Теперь, когда вы меняете один из них, другой изменится.
Ваш пример немного сложнее, потому что вам нужно делать привязки из свойств @NSManaged, которые нельзя сделать Observable
, Это не невозможно, но для работы свойства Person должны поддерживать наблюдение значения ключа (KVO).
Например, учитывая объект Person и метку, вы можете получить свойство из свойства с включенным KVO с помощью метода rValueForKeyPath
а затем привяжите это наблюдаемое к метке, например так:
let person: Person
let nameLabel: UILabel
person.rValueForKeyPath("firstName").bindTo(nameLabel)
Если у вас есть промежуточный объект, как ваш FormItemDescriptor
тогда вам придется сделать его свойства наблюдаемыми.
class FormItemDescriptor {
var tag: Property<String?>
var value: Property<Any?>
}
Теперь вы можете установить привязку
let person: Person
let descriptor: FormItemDescriptor
person.rValueForKeyPath("firstName").bindTo(descriptor.value)
Так как firstName
не наблюдается, вы не можете делать привязку в другом направлении, поэтому вам придется обновлять его каждый раз, когда value
изменения.
descriptor.value.observeNext { value in
person.firstName = value as? NSString
}
Мы также должны были сделать приведение к NSString
так как value
имеет тип Any?
, Вы должны переосмыслить это и посмотреть, сможете ли вы сделать его более сильным.
Обратите внимание, что привязки UIKit поступают из платформы ReactiveUIKit. Проверьте нашу документацию ReactiveKit для получения дополнительной информации.