You do need to wrap your view controller in a SwiftUI struct that conforms to the UIViewControllerRepresentable
protocol. This allows you to use a UIKit view controller in your SwiftUI view hierarchy.
There's a very similar protocol, UIViewRepresentable
, that works for UIKit views that aren't controllers - it works in almost exactly the same way.
So if your UIKit view controller is called MyViewController
, we could wrap it in a Swift view that we'll call MyView
. There are two methods that we have to implement:
struct MyView: UIViewControllerRepresentable {
// autocomplete will give a return value of `some UIViewController`
// but if you replace that with your controller's class name, it
// makes everything clearer
func makeUIViewController(context: Context) -> MyViewController {
// do basic setup in here
return MyViewController()
}
func updateUIViewController(
// you have to specify your UIKit class name here too
_ uiViewController: MyViewController,
context: Context
) {
// do the main configuration of your view controller in here,
// especially if there's SwiftUI state you need the controller
// to react to
///
// You don't have to do anything in this method, but you still have
// to include it. Leave it empty if you're not configuring anything
}
}
That is all you have to do to get a version of your controller to work within SwiftUI's view hierarchy. You have to remember to use the SwiftUI wrapper rather than your UIKit view controller directly, e.g.:
NavigationLink{
MyView()
} label: {
Text("XXX")
}
There's more to do if you need to pass information in to the view controller to set it up, to get it to respond to changes in your SwiftUI state, or if you want to update state based on events or actions in the controller. But that's outside the scope of your question, I think.