• Ask a Question
  • Create a Poll
150
    Ask a Question
    Cancel
    150
    More answer You can create 5 answer(s).
      Ask a Poll
      Cancel

      How to Instantiate UIHostingController with CoreData?

      As a long-time Obj-C dev (since iPhone OS 2) I decided that SwiftUI was the nudge to use Swift! ¯\(ツ)/¯ Thus, I am still trying to understand how a language can be so type-vague in code, and so type-pedantic in the compiler!!!

      Pulling my hair out trying to get Swift/SwiftUI to instantiate a UIHostingController<>, for use with 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")     } } 

      How can I FORCE Swift to INFER the correct/appropriate type?

      What I have tried so far.

      5 let contentView = MyCoreDataView() 

      Compiles/runs, but does not include CoreData.

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

      Compiles, but crashes at instantiation.

      Could not cast value of type ‘SwiftUI.ModifiedContent<MyHostingController.MyCoreDataView, SwiftUI._EnvironmentKeyWritingModifier<__C.NSManagedObjectContext>>’ (…) to ‘MyHostingController.MyCoreDataView’ (…).

      … or is this simply not possible? (yet)

      2 Answers

      Here is the fastest come-in-mind solution – just use AnyView type-eraser.

      Note: any view modifier creates (can create in general) different type of view, that’s why compiler complains in your case – types are different.

      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))     } } 
      Answered by Lavernkaseyeffie on August 31, 2020..

      Posted by OOPer on Apple Dev Forums:

      As you see, modifiers for SwiftUI View returns some opaque type some View which is not revealed to programmers but Swift compiler claims matching the type every here and there…

      One possible solution is creating a wrapper View:

      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)     } } 

      Or you can choose AnyView as the wrapper:

      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)     } } 

      I’m not sure if this works for your case, but please try.

      Answered by Aliwyattdena on August 31, 2020..