gpt4 book ai didi

core-data - 当 SwiftUI 中的相关实体发生更改时,如何更新 @FetchRequest?

转载 作者:行者123 更新时间:2023-12-03 07:34:27 25 4
gpt4 key购买 nike

在 SwiftUI 中 View我有一个 List基于 @FetchRequest显示 Primary 的数据实体和via关系连接Secondary实体。View和它的 List正确更新,当我添加一个新的 Primary具有新的相关次要实体的实体。

问题是,当我更新连接时 Secondary在详细 View 中的项目,数据库得到更新,但更改未反射(reflect)在 Primary 中列表。
显然,@FetchRequest不会被另一个 View 中的更改触发。

当我此后在主 View 中添加新项目时,先前更改的项目最终会得到更新。

作为一种解决方法,我另外更新了 Primary 的一个属性。详细 View 中的实体,更改正确传播到 Primary看法。

我的问题是:
如何强制更新所有相关 @FetchRequests在 SwiftUI 核心数据中?
特别是当我无法直接访问相关实体时/@Fetchrequests ?

Data Structure

import SwiftUI

extension Primary: Identifiable {}

// Primary View

struct PrimaryListView: View {
@Environment(\.managedObjectContext) var context

@FetchRequest(
entity: Primary.entity(),
sortDescriptors: [NSSortDescriptor(key: "primaryName", ascending: true)]
)
var fetchedResults: FetchedResults<Primary>

var body: some View {
List {
ForEach(fetchedResults) { primary in
NavigationLink(destination: SecondaryView(primary: primary)) {
VStack(alignment: .leading) {
Text("\(primary.primaryName ?? "nil")")
Text("\(primary.secondary?.secondaryName ?? "nil")").font(.footnote).foregroundColor(.secondary)
}
}
}
}
.navigationBarTitle("Primary List")
.navigationBarItems(trailing:
Button(action: {self.addNewPrimary()} ) {
Image(systemName: "plus")
}
)
}

private func addNewPrimary() {
let newPrimary = Primary(context: context)
newPrimary.primaryName = "Primary created at \(Date())"
let newSecondary = Secondary(context: context)
newSecondary.secondaryName = "Secondary built at \(Date())"
newPrimary.secondary = newSecondary
try? context.save()
}
}

struct PrimaryListView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

return NavigationView {
PrimaryListView().environment(\.managedObjectContext, context)
}
}
}

// Detail View

struct SecondaryView: View {
@Environment(\.presentationMode) var presentationMode

var primary: Primary

@State private var newSecondaryName = ""

var body: some View {
VStack {
TextField("Secondary name:", text: $newSecondaryName)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.onAppear {self.newSecondaryName = self.primary.secondary?.secondaryName ?? "no name"}
Button(action: {self.saveChanges()}) {
Text("Save")
}
.padding()
}
}

private func saveChanges() {
primary.secondary?.secondaryName = newSecondaryName

// TODO: ❌ workaround to trigger update on primary @FetchRequest
primary.managedObjectContext.refresh(primary, mergeChanges: true)
// primary.primaryName = primary.primaryName

try? primary.managedObjectContext?.save()
presentationMode.wrappedValue.dismiss()
}
}

最佳答案

我也为此苦苦挣扎,并找到了一个非常好的和干净的解决方案:
您必须将行包装在单独的 View 中,并在实体的该行 View 中使用 @ObservedObject。
这是我的代码:
酒单:

struct WineList: View {
@FetchRequest(entity: Wine.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Wine.name, ascending: true)
]
) var wines: FetchedResults<Wine>

var body: some View {
List(wines, id: \.id) { wine in
NavigationLink(destination: WineDetail(wine: wine)) {
WineRow(wine: wine)
}
}
.navigationBarTitle("Wines")
}
}
葡萄酒行:
struct WineRow: View {
@ObservedObject var wine: Wine // !! @ObserveObject is the key!!!

var body: some View {
HStack {
Text(wine.name ?? "")
Spacer()
}
}
}

关于core-data - 当 SwiftUI 中的相关实体发生更改时,如何更新 @FetchRequest?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58643094/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com