连接 Realm 和 SwiftBond 的最佳方式是什么
What is the best way to connect Realm and SwiftBond
我爱Realm and I love Bond。它们都使应用程序创建成为一种乐趣。所以我想知道连接 Realm 和 Bond 的最佳方式是什么?
在 Realm 中,我们可以存储基本类型,例如 Int
、String
,例如但在 Bond 中,我们使用 Dynamic
s 和 Bond
s。我发现连接 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
}
}
但它确实缺乏简洁和优雅,并且会产生大量的锅炉代码。有什么办法可以做得更好吗?
如果您使用
默认 属性 值:
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 或等效观察机制的本地语言支持之前,遗憾的是您将不得不编写一些样板文件。
我考虑了三天,想出了近乎完美的解决方案,没有使用任何样板代码。首先,我为领域模型的包装器创建了一个超级 class:
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") }
}
之后我为每个领域模型创建两个 classes,第一个是实际的领域模型,它存储所有属性:
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() }
}
而这两个 classes 实际上是 link Realm
和 Bond
所需要的:创建新的 TodoModel
实际上会添加到 Realm new RealmTodoModel
和 TodoModel
的 title
和 date
所做的所有更改将自动保存到相应的 Realm
模型!
编辑
我添加了一些功能并将其作为框架发布在 GitHub 上。这里是 link.
借助支持 KVO 和 Bond 4 的 Realm,您可以扩展 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"
}
我爱Realm and I love Bond。它们都使应用程序创建成为一种乐趣。所以我想知道连接 Realm 和 Bond 的最佳方式是什么?
在 Realm 中,我们可以存储基本类型,例如 Int
、String
,例如但在 Bond 中,我们使用 Dynamic
s 和 Bond
s。我发现连接 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
}
}
但它确实缺乏简洁和优雅,并且会产生大量的锅炉代码。有什么办法可以做得更好吗?
如果您使用 默认 属性 值:
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 或等效观察机制的本地语言支持之前,遗憾的是您将不得不编写一些样板文件。
我考虑了三天,想出了近乎完美的解决方案,没有使用任何样板代码。首先,我为领域模型的包装器创建了一个超级 class:
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") }
}
之后我为每个领域模型创建两个 classes,第一个是实际的领域模型,它存储所有属性:
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() }
}
而这两个 classes 实际上是 link Realm
和 Bond
所需要的:创建新的 TodoModel
实际上会添加到 Realm new RealmTodoModel
和 TodoModel
的 title
和 date
所做的所有更改将自动保存到相应的 Realm
模型!
编辑
我添加了一些功能并将其作为框架发布在 GitHub 上。这里是 link.
借助支持 KVO 和 Bond 4 的 Realm,您可以扩展 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"
}