使用核心数据导航到 SwiftUI 中的详细视图

Navigating to detail views in SwiftUI using core data

我正在尝试构建一个示例 BBQ 应用程序来学习 SwiftUI (XCode 11 beta 5),但一直无法弄清楚如何从对象的列表视图导航到对象的详细信息视图来自核心数据。 Xcode 没有帮助,主要是根据我的尝试弹出不相关的错误。

我尝试尽我最大的逻辑能力应用状态、绑定、可观察对象等,但未能破解它。

这是我的列表视图,构建得很好,并允许我导航到目的地(它只是一个包含 id 属性 作为字符串的视图):

struct CookListView: View {

    @ObservedObject var cookListVM: CookListViewModel
    @State var cookCreatorVM = CookCreatorViewModel()

    init() {
        cookListVM = CookListViewModel()
    }

    var body: some View {


        NavigationView {
            List {
                ForEach(cookListVM.cooks, id: \.id) { cook in
                    NavigationLink(destination: Text("\(cook.id)")) {
                        VStack {
                            Text(cook.protein)
                        }
                    }
                }
            }.navigationBarTitle("BBQ")
        }
    }
}

但是如果我像这样更改我的 NavigationLink 目的地:

NavigationView {
    List {
        ForEach(cookListVM.cooks, id: \.id) { cook in
            NavigationLink(destination: CookDetailView(cook: cook)) {
                VStack {
                    Text(cook.protein)
                }
            }
        }
    }
}

Xcode 将不再构建该项目。它给我的错误似乎有些无关,例如 ForEach 行上的 Type '_' has no member 'id',或者如果我从 ForEach 中删除 , id: \.id(由于 Identifiable,我真的不需要),我会得到Type of expression is ambiguous without more contextText(cook.protein) 行。

如果我使用硬编码数组,它会构建并且可以很好地导航。只有在我尝试使用 Core Data 时才会出现此问题。

我的 CookDetailView 看起来像这样:

struct CookDetailView: View {
    var cook: Cook
    var body: some View {
        VStack {
            Text("\(cook.protein!)")
        }
    }
}

Cook 对象本身的模型如下所示:

class CookViewModel: ObservableObject, Identifiable {

    var protein: String = ""
    var type: String = ""
    var id: UUID = UUID()

    init(cook: Cook){
        self.protein = cook.protein!
        self.type = cook.type!
        self.id = UUID()
    }
}

它也是通过 .xcdatamodeld 文件设置的。

我非常乐意添加任何 additional/omitted 代码,例如我如何从核心数据编写 to/reading,如果这会有所帮助的话。

我完全可以理解您对 Xcode 的错误消息感到沮丧。实际错误通常离错误消息很远。 [建议:使用源代码管理并在每次干净编译后提交 ;-)] 您在列表视图中遇到的错误是因为您在详细视图的参数列表中指定了错误的类型。尝试以下操作:

struct CookDetailView: View {

    var cook: CookViewModel

    var body: some View {
        VStack {
            Text("\(cook.name)")
        }
    }
}

顺便说一下,由于您正在获取一个数组,除非您手动发布它们,否则您不会观察到该数组中的更改。我放弃了让我的 NSManagedObject 子类发布它们自己的更改的尝试。有两种方法可以解决这个问题。您可以从 NSFetchedResultsControllercontrollerDidChangeContent 委托调用 objectWillChange,或者您可以在不使用获取结果控制器时观察 NSManagedObjectContextDidSave 通知的同时执行相同的操作。

此答案适用于 Beta 5。在未来的 Beta 中情况肯定会发生变化。