Realm Swift文档指出,您可以使用KVO观察模型类上使用的大多数属性。使用ReactiveCocoa,对于模型类中的每个属性,我创建了一个类似的rac_
前缀属性,它发送值更改,然后我可以使用它来绑定到MVVM样式体系结构中的视图。
示例模型类可能如下所示:
class Post: Object {
dynamic var text = ""
private(set) lazy var rac_text: AnyProperty<String> = { [unowned self] in
return AnyProperty(initialValue: self.name, signal: self.rac_valuesForKeyPath("text", observer: self).toSignal().takeUntil(self.willDeallocSignal())
}()
}
这是非常方便的因为1)它不是来自外部的可变(AnyProperty
vs MutableProperty
和2)只有模型与.takeUntil(self.willDeallocSignal())
一起生存。 (我也想问一下,这里需要[unowned self]
位吗?我不确定self
是否被捕获,总是那么糟糕。
问题来自于List
属性。列表不能标记为动态有意义,它们的类型不能用objective-c表示。关键价值观察工作正常,有一个重要的警告。
使用关系列表属性获取相同的类:
class Post: Object {
let users: List<User> = List<User>()
}
相应的反应性观察属性应该看起来像:
private(set) lazy var rac_users: AnyProperty<List<User>> = {
return AnyProperty(initialValue: self.users, signal: self.rac_valuesForKeyPath("users", observer: self).toSignal().takeUntil(self.willDeallocSignal()))
}()
然而,在观察时,信号不会发出List
个对象,它会发出RLMArray
个对象。我不得不jerryrig一个看起来像的信号发生器:
private(set) lazy var rac_posts: AnyProperty<List<Post>> = { [unowned self] in
return AnyProperty<List<Post>>(initialValue: self.posts, producer: self.rac_valuesForKeyPath("posts", observer: self)
.toSignalProducer()
.assumeNoErrors()
.map { $0 as! RLMArray }
.map { array in
var list = List<Post>()
for i in 0..<array.count {
if let element = array[i] as? Post {
list.append(element)
}
}
return list
})
}()
当然,if let
语句总是失败,因为RLMObject
无法转换为Post
。所以我要么a)一种方法将RLMObject
转换为Object
s或b)在列表属性上发送kvo的方式。我使用传统的KVO测试它并得到了相同的结果。
答案 0 :(得分:1)
您可以使用addNotificationBlock
在Realm Swift中观察List
类型的属性。
此方法采用闭包,在每次更改时调用。至少只要您不阻止运行循环,通知就可能会合并。通过这种机制也会报告初始值,因此您可能会获得额外的信号,这可能是您不期望的。
你应该可以使用Reactive Cocoa连接它,如下所示:
private(set) lazy var rac_posts: AnyProperty<List<Post>> = { [unowned self] in
return AnyProperty<List<Post>>(initialValue: self.posts, signal: Signal<List<Post>>() { [unowned self] observer in
let notificationToken = self.posts.addNotificationBlock { list in
observer.sendNext(list)
}
return ActionDisposable() {
notificationToken.stop()
}
}
}()
合并#3359后,您还会收到细粒度的通知,通知您列表中的详细更改。
答案 1 :(得分:0)
func observeAppVarProperties(properties: [String]) -> Observable<AppVarsObject> {
return Observable.create { observer in
guard let globals = try! Realm().objects(AppVarsObject.self).first else {
observer.onError(NSError(domain: "", code: 0, userInfo: nil))
return Disposables.create()
}
observer.onNext(globals)
let notificationToken = globals.observe { (changed) in
switch changed {
case .change(let propertyChanges):
if propertyChanges.filter({ properties.contains($0.name) }).count > 0 {
observer.onNext(globals)
}
case .deleted:
observer.onNext(globals)
case .error(let error):
observer.onError(error)
}
}
return Disposables.create {
notificationToken.invalidate()
}
}
}