如何使用CoreData实例化UIHostingController?

时间:2020-08-20 11:28:46

标签: ios swift core-data swiftui uihostingcontroller

作为一个长期的Obj-C开发人员(自iPhone OS 2起),我认为SwiftUI是使用Swift的推动力! ¯\ (ツ) /¯ 因此,我仍在尝试理解一种语言如何在代码中如此含糊不清,并在编译器中如此繁琐!!

拔出头发,尝试让Swift / SwiftUI实例化UIHostingController <>,以便与CoreData一起使用

class MyCoreDataHostingController : UIHostingController<MyCoreDataView> {

    required init?(coder: NSCoder) {//Instantiate From Storyboard
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        let contentView = MyCoreDataView().environment(\.managedObjectContext, context)
        super.init(coder: coder, rootView: contentView)
        //Cannot convert value of type 'some View' to expected argument type 'MyCoreDataView'
    }
}

struct MyCoreDataView: View {
    var body: some View {
        Text("Core Data View")
    }
}

如何强制Swift推断正确/合适的类型?

到目前为止我尝试过的。

5 let contentView = MyCoreDataView()

编译/运行,但不包括CoreData。

6 super.init(coder: coder, rootView: contentView as! MyCoreDataView)

编译,但在实例化时崩溃。

无法转换类型为'SwiftUI.ModifiedContent >'的值(...) 到“ MyHostingController.MyCoreDataView”(...)。

...还是这根本不可能? (还)

2 个答案:

答案 0 :(得分:0)

这是最快的精打细算解决方案-只需使用AnyView类型擦除器即可。

注意:任何视图修饰符都会创建(通常可以创建)不同类型的视图,这就是为什么编译器会抱怨您的情况-类型不同。

class MyCoreDataHostingController : UIHostingController<AnyView> {

    required init?(coder: NSCoder) {//Instantiate From Storyboard
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        let contentView = MyCoreDataView().environment(\.managedObjectContext, context)
        super.init(coder: coder, rootView: AnyView(contentView))
    }
}

答案 1 :(得分:0)

OOPer在Apple Dev论坛上发布:

如您所见,SwiftUI View的修饰符会返回一些不透明的类型,某些View不会向程序员显示,但是Swift编译器声称这里和那里都匹配该类型...

一种可能的解决方案是创建包装视图:

class MyCoreDataHostingController : UIHostingController<MyCoreDataViewEnvironmentWrapper> {
    required init?(coder: NSCoder) {//Instantiate From Storyboard
        let contentView = MyCoreDataViewEnvironmentWrapper()
        super.init(coder: coder, rootView: contentView)
    }
}
struct MyCoreDataViewEnvironmentWrapper: View {
    private let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
    var body: some View {
        MyCoreDataView().environment(\.managedObjectContext, context)
    }
}

或者您可以选择AnyView作为包装器:

class MyCoreDataHostingController : UIHostingController<AnyView> {
    required init?(coder: NSCoder) {//Instantiate From Storyboard
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        let contentView = AnyView(MyCoreDataView().environment(\.managedObjectContext, context))
        super.init(coder: coder, rootView: contentView)
    }
}

我不确定这是否适合您的情况,但请尝试。