How can I return opaque type for generic class?
func makeFAQController() -> UIHostingController<some View> {
let viewModel = FAQViewModel()
let view = FAQView().environmentObject(viewModel)
let controller = UIHostingController(rootView: view)
return controller
}
Error: Cannot convert value of type 'UIHostingController<some View>' to type 'UIHostingController<FAQView>' in coercion
func makeFAQController() -> UIHostingController<FAQView> {
let viewModel = FAQViewModel()
let view = FAQView().environmentObject(viewModel)
let controller = UIHostingController(rootView: view)
return controller
}
Cannot convert value of type 'UIHostingController<some View>' to type 'UIHostingController<FAQView>' in coercion
I want to avoid type erasure if possible.
CodePudding user response:
You should return base class (there is nothing more generic then base class, probably only meta NSObject
), so
func makeFAQController() -> UIViewController { // << here !!
let viewModel = FAQViewModel()
let view = FAQView().environmentObject(viewModel)
let controller = UIHostingController(rootView: view)
return controller
}
CodePudding user response:
You might as well use type-erased AnyView
here:
func makeFAQController() -> UIHostingController<AnyView> {
let viewModel = FAQViewModel()
let view = FAQView().environmentObject(viewModel)
let controller = UIHostingController(rootView: AnyView(view))
return controller
}
Another approach avoiding AnyView
would be to make the enclosing class of makeFaqController
method generic and store in it a closure/viewBuilder to use as view to host at creation time:
class FAQMaker<U: View> {
fileprivate let _prepare: (FAQView) -> U
init(_ prepare: @escaping (FAQView) -> U) {
self._prepare = prepare
}
func makeFAQController() -> UIHostingController<U> {
let prepared = _prapare(FAQView())
return UIHostingController(rootView: prepared)
}
}
The former approach worked for me fine to wrap SwiftUI views into UICollectionReusableView
.