SwiftUI 中 FetchRequest 的隔离托管对象上下文

问题描述

在 SwiftUI 视图中,认情况下 FetchRequestmanagedobjectContext 环境值中获取。如果视图想要提取isolated context 中,例如在不污染其他视图上下文的情况下进行可丢弃的编辑,它如何更改 FetchRequest 使用的上下文?

一种选择是将视图包装在创建隔离上下文的外部视图中,然后使用它调用包装的视图:

var body: some View {
    WrappedView().environment(\.managedobjectContext,isolatedContext)
}

然而,这很乏味。您必须创建两个视图并通过包装器传递所有包装视图的参数。有没有更好的方法来告诉 FetchRequest 使用哪个上下文?

解决方法

如果您使用 Apple 作为初创公司提供的标准 PersistentController,您可以尝试使用

.environment(\.managedObjectContext,privateContext)

您的 View 需要此属性才能使其工作。 @State 应该不是必需的,因为更改是通过其他方式(例如通知)在后台完成的。

let privateContext = PersistenceController.shared.container.newBackgroundContext()

调用 newBackgroundContext() 方法会导致持久性容器创建并返回一个新的 NSManagedObjectContext,concurrencyType 设置为 NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType。这个新上下文将直接与 NSPersistentStoreCoordinator 相关联,并设置为自动使用 NSManagedObjectContextDidSave 广播。

然后使用 Apple 的大部分示例代码对其进行测试。

struct SampleSharedCloudKitApp: App {
    let privateContext = PersistenceController.shared.container.newBackgroundContext()
    var body: some Scene {
        WindowGroup {
            VStack{
                Text(privateContext.description) //Added this to match with ContentView
                ContentView()
                    .environment(\.managedObjectContext,privateContext)
                    //Once you pass the privateContext here everything below it will have the privateContext
                    //You don't need to connect it with @FetchRequest by any other means
            }
        }
    }
}

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp,ascending: true)],animation: .default)
    private var items: FetchedResults<Item>

    var body: some View {
        List {
            Text((items.first!.managedObjectContext!.concurrencyType == NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType).description) //This shows true
            Text(items.first!.managedObjectContext!.description)// This description matches the parent view
            Text(viewContext.description)// This description matches the parent view

另外,需要注意的是你必须设置

container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyStoreTrump

为了让主上下文显示在保存 privateContext 后所做的更改。我在 PersistenceController 闭包后立即将其放入 init loadPersistentStores

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...