我有以下 Realm 对象 - Make 保存模型列表。
class Make: Object, ObjectKeyIdentifiable {
@Persisted var name: String = ""
@Persisted var models: RealmSwift.List<Model>
}
class Model: Object, ObjectKeyIdentifiable {
@Persisted var name: String = ""
@Persisted var flag: Bool = false
@Persisted(originProperty: "models") var make: LinkingObjects<Make>
}
我有一个以下视图,它获取所有品牌并将它们呈现在列表中。 点击给定的 Make 将打开一个包含其模型列表的工作表,或者根据部分将相同的视图推送到当前的 NavigationStack 上(这只是为了显示差异)
struct ContentView: View {
@ObservedResults(Make.self) private var makes
@State private var selected: Make?
var body: some View {
NavigationStack {
List {
Section {
ForEach(makes) { make in
Text(make.name)
.onTapGesture {
selected = make
}
}
}
Section {
ForEach(makes) { make in
NavigationLink {
MakeView(make: make)
} label: {
Text(make.name)
}
}
}
}
.sheet(item: $selected) { make in
MakeView(make: make)
}
}
}
}
MakeView 有一个模型列表,点击模型会打开另一个视图,我们可以在其中编辑模型的名称
struct MakeView: View {
@ObservedRealmObject var make: Make
var body: some View {
NavigationStack {
List {
ForEach(make.models) { model in
NavigationLink {
EditModelView(model: model)
} label: {
HStack {
Text(model.name)
Spacer()
Image(systemName: model.flag ? "checkmark.circle" : "x.circle")
}
}
}
}
}
}
}
最后是允许我们编辑模型对象的 EditModelView
struct EditModelView: View {
@ObservedRealmObject var model: Model
var body: some View {
Form {
TextField(text: $model.name) {
Text("Name")
}
Toggle("Flag", isOn: $model.flag)
}
}
}
这里的问题是,如果我通过 .sheet 呈现 MakeView 并转到 EditViewModel,如果我更改 TextField 或 Toggle 中的值并返回到上一个视图 (MakeView),则更改不存在,实际上只存在一个更改。如果我更改“名称”字段中的一个字母,它将被更改,但任何下一个字母都不会出现,当仅反映一个值更改并且任何后续更改都将不可见时,它在切换上会更好地可见。如果我关闭 MakeView 并再次打开它,更改就在那里。因此,数据库已正确更新,但在更改标志的模型名称后视图不会更新。 如果将 MakeView 推送到 NavigationStack 上,则不会出现此问题。 根据我的理解,ObservedObject 应该跟踪更改并相应地更新视图。
我对 SwiftUI 还很陌生,所以我不确定这是否是 RealmSwift 方面的错误,或者我的经验不足,不明白应该如何实现。
有一些解决方案,但问题是视图没有刷新(并且无法按原样关闭工作表(需要添加)。所以这是基于问题中的代码的an答案,但还有很多其他的。
尝试将代码更改为以下内容(我删除了工作代码部分)
Section {
ForEach(makes) { make in
Text(make.name)
.onTapGesture {
selected = make
}
}
}
}
.sheet(item: $selected,
onDismiss: didDismiss) { make in
MakeView(make: make)
}
.onTapGesture {
selected = nil
}
}
}
func didDismiss() {
// Handle the dismissing action.
}
请同时查看 ForEach 初始化器
实例仅读取所提供数据的初始值,不需要跨更新识别视图。要在动态范围内按需计算视图,请使用 ForEach/init(_:id:content:)。