访问 managedObjectContext 以在 @main 应用程序中执行 @FetchRequest

Access managedObjectContext to execute a @ FetchRequest in the @main app

我正在创建一个带有动态菜单项列表的 SwiftUI macOS 应用程序,该列表将基于用户的数据创建:

这是我尝试创建菜单的方式:

@main
struct MacOSApp: App {

    @AppStorage("tagFilter") private var tagFilter: String = ""

    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Tag.name, ascending: true)], animation: .default)
    private var tags: FetchedResults<Tag>

    var body: some Scene {
        WindowGroup {
            ContentView(menuBarActionsState: menuBarActionsState)
                .environment(\.managedObjectContext, storageProvider.persistentContainer.viewContext)
        }.commands {
            CommandGroup(before: CommandGroupPlacement.toolbar) {
                Picker("Filter by Tag", selection: $tagFilter) {
                    ForEach(tags, id: \.self) { tag in
                        Text(tag.name ?? "").tag(tag.id ?? "")
                    }
                }
            }
        }
    }
}

问题是,我在 @main 应用程序中没有 managedObjectContext,因为这是应用程序的起点。它被注入到 ContentView 的环境中,但菜单是在其之上创建的。

因为我没有managedObjectContext,运行时出现如下错误:

Context in environment is not connected to a persistent store coordinator:  <NSManagedObjectContext: 0x6000039a2700>

我们可以在 @main 应用级别访问 managedObjectContext 吗?或者我能以某种方式在我的 @FetchRequest 中注入 managedObjectContext,以便我可以在 @main 应用程序中使用它来构建菜单吗?

根据它们使用的变量将您的视图数据结构分解为尽可能小。这称为严格失效,应该可以解决问题。

@main
struct MacOSApp: App {

    var body: some Scene {
        WindowGroup {
            ContentView(menuBarActionsState: menuBarActionsState)
                .environment(\.managedObjectContext, storageProvider.persistentContainer.viewContext)
        }.commands {
            CommandGroup(before: CommandGroupPlacement.toolbar) {
                TagsView()
            }
            .environment(\.managedObjectContext, storageProvider.persistentContainer.viewContext)
        }
    }
}


struct TagsView: View {
    @AppStorage("tagFilter") private var tagFilter: String = ""

    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Tag.name, ascending: true)], animation: .default)
    private var tags: FetchedResults<Tag>

    var body: some View {
         Picker("Filter by Tag", selection: $tagFilter) {
             ForEach(tags, id: \.self) { tag in
                 Text(tag.name ?? "").tag(tag.id ?? "")
             }
         }
    }
}