如何实现Realm嵌套对象变更通知向上层传播?求已有实现分享
实现Realm嵌套对象的通知传播扩展
Realm官方SDK出于性能优化考量(避免深度嵌套对象引发的冗余通知),默认不支持嵌套对象(如EmbeddedObject)的变更通知向上传播到父对象,但我们可以通过自定义扩展补全这个功能。
以下是可直接复用的实现方案,能让父对象监听到其嵌套的EmbeddedObject的变更:
核心扩展代码
import RealmSwift extension Object { func observeNestedChanges(completion: @escaping () -> Void) -> NotificationToken { // 监听当前对象的直接变更 let selfToken = observe { [weak self] change in guard case .change(_) = change else { return } completion() } // 监听所有嵌套的EmbeddedObject属性 let nestedTokens = Mirror(reflecting: self).children.compactMap { child -> NotificationToken? in guard let propertyName = child.label, let embeddedObject = self?[propertyName] as? EmbeddedObject else { return nil } return embeddedObject.observe { change in guard case .change(_) = change else { return } completion() } } // 组合所有通知令牌统一管理 return CompositeNotificationToken(tokens: [selfToken] + nestedTokens) } } // 自定义复合通知令牌,管理多个监听令牌 class CompositeNotificationToken: NotificationToken { private let tokens: [NotificationToken] init(tokens: [NotificationToken]) { self.tokens = tokens super.init() } override func invalidate() { tokens.forEach { $0.invalidate() } super.invalidate() } }
使用示例
结合你提供的对象模型,使用方式如下:
final class ParentObject: Object { @Persisted var embeddedObject: SomeEmbeddedObject? } final class SomeEmbeddedObject: EmbeddedObject { @Persisted var text: String = "" } // 初始化Realm及对象 let realm = try! Realm() let parentObject = ParentObject() parentObject.embeddedObject = SomeEmbeddedObject() try! realm.write { realm.add(parentObject) } // 监听父对象及嵌套对象的变更 let notificationToken = parentObject.observeNestedChanges { print("嵌套对象或父对象发生变更") } // 触发嵌套对象变更 try! realm.write { parentObject.embeddedObject!.text = "Hello World" } // 不再监听时销毁令牌 // notificationToken.invalidate()
关键说明
- 该扩展会监听对象所有直接嵌套的
EmbeddedObject属性,若需支持多层嵌套,可修改observeNestedChanges方法实现深度递归监听 - 通过
CompositeNotificationToken统一管理令牌,避免遗漏销毁导致内存泄漏 - 若嵌套对象可能被置为
nil,可扩展逻辑,在父对象变更时重新监听新的嵌套对象(当前示例仅监听初始存在的嵌套对象)
内容的提问来源于stack exchange,提问作者Den Andreychuk
相关产品推荐
相关产品推荐

