3

作为一名长期的 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, SwiftUI._EnvironmentKeyWritingModifier<__C.NSManagedObjectContext>>' (...) 类型的值转换为 'MyHostingController.MyCoreDataView' (...)。

...或者这根本不可能?(然而)

4

2 回答 2

1

这是最快的想到的解决方案 - 只需使用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))
    }
}
于 2020-08-20T12:11:02.020 回答
0

OOPer 在 Apple 开发论坛上发布:

如您所见,SwiftUI View 的修饰符返回一些不透明的类型 some 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)
    }
}

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

于 2020-08-21T10:28:51.543 回答