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

SwiftUI配置Atlas Device Sync关联时触发RLMException错误求助

Realm关联对象写入错误排查与修复

错误:因未捕获的异常'RLMException'终止应用,原因:'无法在写入事务外修改托管RLMArray。'

我按照官方文档实现写入操作原本正常,但添加对象关联后触发上述错误。相关代码如下:

模型定义

class Dog: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var name = ""
    @Persisted var owner: Person? // 我认为这是错误原因
    
    convenience init(name: String = "", owner: Person) {
            self.init()
            self.owner = owner
    }
}

class Person: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var name = ""
    @Persisted var dogs: List<Dog>
    
    convenience init(name: String) {
        self.init()
        self.name = name
    }
}

视图代码

struct AddDogToPersonView: View {
    
    @ObservedRealmObject var person: Person
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        Form {
            Section {
                Button(action: {
                    $person.dogs.append(Dog(name: "Benny", owner: person))
                    dismiss.callAsFunction()
                }) {
                    Text("Save")
                }
                Button(action: {
                    dismiss.callAsFunction()
                }) {
                    Text("Cancel")
                }
            }
        }
    }
}

我怀疑这与Dog引用其Owner的逻辑有关,具体代码行如下:

$person.dogs.append(Dog(name: "Benny", owner: person))

问题原因

问题出在初始化Dog时直接给owner赋值了已托管到Realm的person对象——这个赋值操作并没有在写入事务内执行。虽然$person.dogs.append()会触发Realm的自动事务,但创建Dog并设置owner的步骤是在事务外完成的,违反了Realm必须在事务内修改托管对象的规则。

修复方案

方案1:利用绑定在自动事务内设置关联

通过$person.dogs.append()的返回值获取新Dog的绑定,在自动事务内完成owner赋值:

Button(action: {
    let dogBinding = $person.dogs.append(Dog(name: "Benny"))
    dogBinding.owner.wrappedValue = person
    dismiss()
}) {
    Text("Save")
}

同时建议修改Dog的便利初始化方法,将owner设为可选参数:

convenience init(name: String = "", owner: Person? = nil) {
    self.init()
    self.name = name
    self.owner = owner
}

方案2:手动开启写入事务

显式开启Realm写入事务,在事务内完成所有操作:

Button(action: {
    guard let realm = person.realm else { return }
    try! realm.write {
        let dog = Dog(name: "Benny", owner: person)
        person.dogs.append(dog)
    }
    dismiss()
}) {
    Text("Save")
}

内容的提问来源于stack exchange,提问作者tintin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:50:16