SwiftUI 和 CoreData:将 FetchResults 传递给 DetailView 并更新它们

Posted

技术标签:

【中文标题】SwiftUI 和 CoreData:将 FetchResults 传递给 DetailView 并更新它们【英文标题】:SwiftUI and CoreData : passing FetchResults to a DetailView and updating them 【发布时间】:2021-03-01 18:19:04 【问题描述】:

代码已更新以反映下面的答案。仍然愿意跳过$newName 并执行TextField("New name...", text: $pcard.name) 之类的操作,但这会引发错误。


长时间的搜索者第一次提问。 *** 非常宝贵。

寻找有关在详细信息视图中更新核心数据实体的单个“行”的最佳做法的一些指导。显然,我正在解决这个问题,因为我无法让它工作,而且似乎没有太多关于这个看似简单的特定用例的讨论。

我的应用程序有一个标准的 MasterList/Detail 结构,我想将在详细视图中进行的更新绑定到在列表视图中获取的实体。

下面的代码,这是我感兴趣的传递/绑定/更新部分。任何帮助表示赞赏,无论是概念上的(这是它的设计工作方式)还是实际的(这样做)。

谢谢。

import SwiftUI

struct ListView: View 
    @Environment(\.managedObjectContext) private var viewContext
    
    @FetchRequest(
        entity: PCard.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \PCard.name, ascending: true)],
        animation: .default
    ) private var pcards: FetchedResults<PCard>
    
    var body: some View 
        NavigationView 
            List 
                ForEach(pcards)  pcard in
                    NavigationLink(destination: DetailView(pcard: pcard)) 
                        Text(pcard.name ?? "no name specified")
                    
                
            
            .navigationTitle("My Cards")
        
    


struct DetailView: View 
    @Environment(\.managedObjectContext) private var viewContext
    @State private var newName: String = ""
    
    @ObservedObject var pcard: PCard
    
    var body: some View 
        
        VStack 
            Text(pcard.name ?? "no name specified").font(.largeTitle)
            TextField("New name...", text: $newName).textFieldStyle(RoundedBorderTextFieldStyle())
            Button(action: 
                pcard.name = newName
                do 
                    try viewContext.save()
                 catch 
                    let nsError = error as NSError
                    fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                
                
            ) 
                //label
                Label("Update", systemImage: "sparkles")
            
            Spacer()
        
        .padding()
        
    


struct ListView_Previews: PreviewProvider 
    static var previews: some View 
        ListView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    


【问题讨论】:

核心数据实体已经默认在内部确认到 ObservableObject 协议,因此您可以尝试使用 ObservedObject 包装器,而不是传递 Binding,并测试您的调用。 --> @ObservedObject var pcard: PCard 行得通!我已经更新了上面的代码以反映。仍然想知道是否有办法取消 $newItem 状态/绑定并将文本字段直接绑定到 pcard.name?不确定这是否可能或语法是什么。 核心数据属性是可选的,这里是你需要的解决方案***.com/questions/57021722/swiftui-optional-textfield。请不要更新现有的帖子,如果您的代码有其他问题,请发新帖子。 【参考方案1】:

无需创建@State newName。 @ObservedObject 已经做了你想要的。请阅读这篇文章: https://purple.telstra.com/blog/swiftui---state-vs--stateobject-vs--observedobject-vs--environme

【讨论】:

以上是关于SwiftUI 和 CoreData:将 FetchResults 传递给 DetailView 并更新它们的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:如何将 CoreData 与动态过滤器相加?

保存数据时出现问题,将 CoreData 与 SwiftUI 一起使用

SwiftUI 和 CoreData:将 FetchResults 传递给 DetailView 并更新它们

无法在 SwiftUI 中使用 ForEach 和 CoreData 将数据正确传递给模态演示

SwiftUI CoreData - 如何更新获取请求和列表

在 CoreData 记录中进行更改,SwiftUI