首页 > 解决方案 > 如何在 SwiftUI 表单中使用 Realm

问题描述

由于未捕获的异常“RLMException”而终止应用程序,原因:“尝试在写入事务之外修改对象 - 首先在 RLMRealm 实例上调用 beginWriteTransaction。”

对托管对象的所有更改(添加、修改和删除)都必须在写入事务中完成。例如,

// Update an object with a transaction
try! realm.write {
    author.name = "Thomas Pynchon"
}

可以使 Realm 子类符合 ObservableObject。但是,我看不到如何在 SwiftUI 中使领域属性可更新。下面的领域属性示例。

@objc dynamic var myName: String = "Adam"

Realm 基于 @objc 动态变量自动设置模式。我看不到在领域属性上获取 @Published 的方法。SwiftUI 将呈现一个 TextField,但在编辑该值时会崩溃。

TextField("Quantity (\(shoppingItem.myUnit!.myName))", value: $shoppingItem.stdQty, formatter: basicFormat)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.numbersAndPunctuation)

有没有办法将 SwiftUI 状态更改包装在 Realm 写入事务中?

标签: realmswiftui

解决方案


考虑 Realm 属性,stdQty 如下所示。它只能在写入事务中更改。

import RealmSwift
import Combine

class ShoppingItems: Object, ObservableObject    
    let objectWillChange = PassthroughSubject<Void, Never>()
    @objc dynamic var stdQty: Double = 1

如果没有原始问题中的错误,您将无法绑定 stdQty。但是,您可以创建一个可以绑定的计算变量。

    var formQty: Double {
        get {
            return stdQty
        } 
        set {
            objectWillChange.send()
            if let sr = self.realm {
                try! sr.write {
                    stdQty = newValue
                }
            }
        }
    }

绑定计算的变量可以正常工作。

TextField("Quantity (\(shoppingItem.myUnit!.myName))", value: $shoppingItem.formQty, formatter: basicFormat)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.numbersAndPunctuation)

答案限制:objectWillChange 仅由计算变量触发。表格的变化反映在表格中。领域中的更改尚未触发组合 objectWillChange。


推荐阅读