环境变量不会传递到子视图(Environment variable not passed to Su

2019-10-29 06:39发布

我想开始使用核心数据及SwiftUI,因此创建使用最新的Xcode 11.1 GM新watchOS项目。

然后,我复制这两个persistentContainersaveContext从一个全新的iOS项目(启用核心数据),从而获得核心数据的能力。

从那以后,我修改了HostingController返回AnyView ,并设置变量的环境。

class HostingController: WKHostingController<AnyView> {
    override var body: AnyView {

        let managedObjectContext = (WKExtension.shared().delegate as! ExtensionDelegate).persistentContainer.viewContext


        return AnyView(ContentView().environment(\.managedObjectContext, managedObjectContext))
    }
}

现在我可以访问上下文里面ContentView但不是在它的子视图
但是,那不是它是如何打算呢? 据我所知,所有的子视图应该从它的超视图继承它的环境,对不对?

眼下,访问它里面的子观点,我只是重新设置环境变量,就像这样:

ContentView.swift

NavigationLink(destination: ProjectsView().environment(\.managedObjectContext, managedObjectContext)) {
    HStack {
        Image(systemName: "folder.fill")
        Text("Projects")
    }
}

一旦我删除里面内容查看该.environment()的参数,该应用程序会崩溃,因为没有上下文加载的?

该错误消息是Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x804795e0>

ProjectsView.swift

struct ProjectsView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    [...]
}

但同样,这不可能是正确的? 所以,这里什么导致错误?

Answer 1:

我能够通过固定起来解决这个HostingController ,保障CoreData堆栈是鉴于施工前安装。 首先,让我们确保CoreData堆准备去。 在ExtensionDelegate

class ExtensionDelegate: NSObject, WKExtensionDelegate {

    let persistentContainer = NSPersistentContainer(name: "Haha")

    func applicationDidFinishLaunching() {
        persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
            // handle this
        })
    }
}

我有麻烦时,这个属性是lazy ,所以我将它设置明确。 如果您遇到计时问题,使loadPersistentStores用旗语来调试同步调用,然后弄清楚如何延缓笔尖实例直到闭合稍后被调用。

接下来,让我们固定HostingController ,通过使一个恒定视图上下文的引用。 WKHostingController是一个对象,而不是一个结构。 所以现在我们有:

class HostingController: WKHostingController<AnyView> {

    private(set) var context: NSManagedObjectContext!

    override func awake(withContext context: Any?) {
        self.context = (WKExtension.shared().delegate as! ExtensionDelegate).persistentContainer.viewContext
    }

    override var body: AnyView {
        return AnyView(ContentView().environment(\.managedObjectContext, context))
    }
}

现在,任何子视图应该获得商务部。 下面现在对我的作品:

struct ContentView: View {

    @Environment(\.managedObjectContext) var moc: NSManagedObjectContext

    var body: some View {
        VStack {
            Text("\(moc)")
            SubView()
        }
    }
}

struct SubView: View {

    @Environment(\.managedObjectContext) var moc: NSManagedObjectContext

    var body: some View {
        Text("\(moc)")
            .foregroundColor(.red)
    }
}

您应该看到MOC的地址在上面和下面的红白色, 而不调用.environmentSubView



Answer 2:

在您要访问您的managedObjectContext你需要声明它像这样每个视图:

@Environment(\.managedObjectContext) var context: NSManagedObjectContext

你不把它的看法,它被传来传去给你。 而且不要忘记导入CoreData以及在这些文件中。



文章来源: Environment variable not passed to Subviews