You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:06:41