我爱Realm,我爱Bond。它们都使应用程序创建成为一种乐趣。所以我想知道连接Realm和Bond的最佳方式是什么?
在Realm中,我们可以存储基本类型,例如Int
,String
,例如但在邦德,我们与Dynamic
和Bond
合作。我发现连接Realm和Bond的唯一方法是:
class TestObject: RLMObject {
dynamic var rlmTitle: String = ""
dynamic var rlmSubtitle: String = ""
var title: Dynamic<String>
var subtitle: Dynamic<String>
private let titleBond: Bond<String>!
private let subtitleBond: Bond<String>!
init(title: String, subtitle: String) {
self.title = Dynamic<String>(title)
self.subtitle = Dynamic<String>(subtitle)
super.init()
self.titleBond = Bond<String>() { [unowned self] title in self.rlmTitle = title }
self.subtitleBond = Bond<String>() { [unowned self] subtitle in self.rlmSubtitle = subtitle }
self.title ->> titleBond
self.subtitle ->> subtitleBond
}
}
但它肯定缺乏简洁和优雅,并产生大量的锅炉代码。有没有办法做得更好?
答案 0 :(得分:6)
Realm支持KVO和Bond 4,您可以扩展Realm对象以提供Observable变体。它有一些样板,但它干净而没有黑客。
class Dog: Object {
dynamic var name = ""
dynamic var birthdate = NSDate(timeIntervalSince1970: 1)
}
extension Dog {
class ObservableDog {
let name: Observable<String>
let birthdate: Observable<NSDate>
init(dog: Dog) {
name = Observable(object: dog, keyPath: "name")
birthdate = Observable(object: dog, keyPath: "birthdate")
}
}
func observableVariant() -> Dog.ObservableDog {
return ObservableDog(dog: self)
}
}
比你能做的更多:
let myDog = Dog().observableVariant()
myDog.name.observe { newName in
print(newName)
}
myDog.name.bindTo(nameLabel.bnd_text)
realm.write {
myDog.name.value = "Jim"
}
答案 1 :(得分:1)
如果使用的话,你可能会简化你正在使用的模式 默认属性值:
class TestObject: RLMObject {
dynamic var rlmTitle = ""
dynamic var rlmSubtitle = ""
var title: Dynamic<String>
var subtitle: Dynamic<String>
private let titleBond = Bond<String>() { [unowned self] title in self.rlmTitle = title }
private let subtitleBond = Bond<String>() { [unowned self] subtitle in self.rlmSubtitle = subtitle }
init(title: String, subtitle: String) {
self.title = Dynamic<String>(title)
self.subtitle = Dynamic<String>(subtitle)
self.title ->> titleBond
self.subtitle ->> subtitleBond
super.init()
}
}
如果Bond的->>
运算符返回,则可以删除另外两行代码
左值,这样你就可以self.title = Dynamic<String>(title) ->> titleBond
。
但最终,在Swift对KVO或同等观察机制提供本地语言支持之前,你很遗憾不得不写一些样板文件。
答案 2 :(得分:1)
我已经考虑了这三天了,并提出了几乎完美的解决方案,它不使用任何样板代码。首先,我为领域模型的包装器创建了一个超类:
class BondRealmBaseClass {
private var realmModel: RLMObject!
private let realm = RLMRealm.defaultRealm()
private var bonds = NSMutableArray()
init(){
realmModel = createRealmModel()
realm.beginWriteTransaction()
realm.addObject(realmModel)
realm.commitWriteTransaction()
createBonds()
}
init(realmModel: RLMObject){
self.realmModel = realmModel
createBonds()
}
func createBondFrom<T>(from: Dynamic<T>, toModelKeyPath keyPath: String){
from.value = realmModel.valueForKeyPath(keyPath) as T
let bond = Bond<T>() { [unowned self] value in
self.realm.beginWriteTransaction()
self.realmModel.setValue(value as NSObject, forKey: keyPath)
self.realm.commitWriteTransaction()
}
from ->| bond
bonds.addObject(bond)
}
//MARK: - Should be overriden by super classes
func createBonds(){ fatalError("should be implemented in supreclass") }
func createRealmModel() -> RLMObject{ fatalError("should be implemented in supreclass") }
}
在每个领域模型之后,我创建两个类,首先是实际领域模型,它存储所有属性:
class RealmTodoModel: RLMObject {
dynamic var title = ""
dynamic var date = NSDate()
}
,第二个是围绕领域模型的包装器:
class TodoModel : BondRealmBaseClass{
let title = Dynamic("")
let date = Dynamic(NSDate())
override func createBonds(){
createBondFrom(title, toModelKeyPath: "title")
createBondFrom(date, toModelKeyPath: "date")
}
override func createRealmModel() -> RLMObject { return RealmTodoModel() }
}
这两个类实际上只需要链接Realm
和Bond
:创建新TodoModel
实际上会添加到Realm新RealmTodoModel
以及使用{进行的所有更改{1}} TodoModel
和title
将自动保存到相应的date
模型中!
我添加了一些功能并将其作为GitHub上的框架发布。这是link。