Swift如何实现双向绑定?
How to implement two way binding with Swift?
如何使用 Swift 2.0 实现双向数据绑定?
假设我有以下型号 class(使用 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
属性?
所以模型中的更改会出现在表单中,反之亦然?
Swift 不支持开箱即用的绑定,但您可以使用 ReactiveKit.
等框架实现它们
例如,当您声明一个 observable 属性 时,您可以将它绑定到另一个 observable 属性。
let numberA: Property<Int>
let numberB: Property<Int>
numberA.bindTo(numberB)
要进行双向,也只需在其他方向绑定即可:
numberB.bindTo(numberA)
现在,只要你改变其中任何一个,另一个也会改变。
不过你的例子有点难,因为你需要从 @NSManaged 属性中进行绑定,而这些属性是无法进行的 Observable
。这不是不可能,但是要使 Person 的属性起作用,应该支持键值观察 (KVO)。
例如,给定一个 Person 对象和一个标签,您可以使用方法 rValueForKeyPath
从启用 KVO 的 属性 中获取一个 属性,然后将该可观察对象绑定到标签,像这样:
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 文档以获取更多信息。
如何使用 Swift 2.0 实现双向数据绑定?
假设我有以下型号 class(使用 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
属性?
所以模型中的更改会出现在表单中,反之亦然?
Swift 不支持开箱即用的绑定,但您可以使用 ReactiveKit.
等框架实现它们例如,当您声明一个 observable 属性 时,您可以将它绑定到另一个 observable 属性。
let numberA: Property<Int>
let numberB: Property<Int>
numberA.bindTo(numberB)
要进行双向,也只需在其他方向绑定即可:
numberB.bindTo(numberA)
现在,只要你改变其中任何一个,另一个也会改变。
不过你的例子有点难,因为你需要从 @NSManaged 属性中进行绑定,而这些属性是无法进行的 Observable
。这不是不可能,但是要使 Person 的属性起作用,应该支持键值观察 (KVO)。
例如,给定一个 Person 对象和一个标签,您可以使用方法 rValueForKeyPath
从启用 KVO 的 属性 中获取一个 属性,然后将该可观察对象绑定到标签,像这样:
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 文档以获取更多信息。