我想观察领域数据库的对象计数。 我写了这种方法:
let realm = try? Realm()
self.notificationToken = realm?.objects(AnalyticsEventDto.self).observe { _ in
if let count = realm?.objects(AnalyticsEventDto.self).count {
observer.send(value: count)
}
}
还有另一种方法可以做到这一点吗? 谢谢
我会使用RealmCollectionChange
参数,而不是在闭包中创建新的Results
对象。这也允许您处理错误:
let realm = try? Realm()
self.notificationToken = realm?.objects(AnalyticsEventDto.self).observe { change in
switch change {
case .initial(let results):
observer.send(value: results.count)
case .update(let results, deletions: _, insertions: _, modifications: _):
observer.send(value: results.count)
case .error(let error):
observer.send(error: error)
}
}
但是一个更 ReactiveSwifty 的方法可能是包装整个 Realm 集合通知 API 以使其是响应式的。这有点复杂,但它更通用,可能在代码中的多个位置使用:
/// We want to send errors via the `ReactiveSwift` error event, so create a new `CollectionChange` enum that
/// mimics `RealmCollectionChange` except it doesn't have an `error` case.
enum CollectionChange<CollectionType> {
case initial(CollectionType)
case update(CollectionType, deletions: [Int], insertions: [Int], modifications: [Int])
}
/// Extending `ReactiveExtensionsProvider` and `Reactive` is the standard way to add reactive extensions
/// to existing types in a way that avoids name collisions.
extension Results: ReactiveExtensionsProvider { }
extension Reactive where Base: RealmCollection {
/// This wraps Realm collection notifications in a very general reactive way.
private func changeNotificationsRaw() -> SignalProducer<RealmCollectionChange<Base>, Never> {
return SignalProducer { [base = self.base] observer, lifetime in
let token = base.observe { change in
observer.send(value: change)
}
lifetime.observeEnded {
token.invalidate()
}
}
}
/// This just maps `RealmCollectionChange` to our own `CollectionChange` type while translating errors
/// to ReactiveSwift error events.
func changeNotifications() -> SignalProducer<CollectionChange<Base>, Error> {
return changeNotificationsRaw().flatMap(.concat) { realmChange -> SignalProducer<CollectionChange<Base>, Error> in
switch realmChange {
case .initial(let collection):
return SignalProducer(value: .initial(collection))
case let .update(collection, deletions, insertions, modifications):
return SignalProducer(value: .update(collection, deletions: deletions, insertions: insertions, modifications: modifications))
case .error(let err):
return SignalProducer(error: err)
}
}
}
}
然后你可以像这样使用它:
realm.objects(AnalyticsEventDto.self).reactive.changeNotifications()
.map { change -> Int in
switch change {
case .initial(let results):
return results.count
case .update(let results, _, _, _):
return results.count
}
}
.take(during: self.lifetime)
.start { event in
print(event)
}