I am working to implement some SwiftUI content into my existing app. I currently have a UIViewController, which hosts a MTKView for camera preview.
I have created a new SwiftUI view, which is now my root view, as set in my SceneDelegate.swift
file. The SwiftUI view loads at launch, as expected. Now, I would like to create a segue in which, when a user taps on a row in my List, it will segue, full-screen to my existing UIViewController. Here is how I'm calling that;
var body: some View {
VStack {
NavigationView {
List(sessionTypes) { session in
NavigationLink(destination: CameraControllerWrapper()) {
SessionRow(session: session)
.frame(height: 40.0)
}
}
.navigationBarTitle(Text("Camera Types"))
}
}
}
For posterity, here is my CameraControllerWrapper
UIViewControllerRepresentable;
struct CameraControllerWrapper: UIViewControllerRepresentable {
typealias UIViewControllerType = CameraController
func makeUIViewController(context: UIViewControllerRepresentableContext<CameraControllerWrapper>) -> CameraControllerWrapper.UIViewControllerType {
return CameraController()
}
func updateUIViewController(_ uiViewController: CameraControllerWrapper.UIViewControllerType, context: UIViewControllerRepresentableContext<CameraControllerWrapper>) {
//
}
}
While this "works," my app crashes as soon as the CameraController is called, as it seems any of my IBOutlets cannot be found. CameraController is a UIViewController built in the storyboard.
I managed to resolve this by realizing that I needed to instantiate the UIViewController from the Storyboard, and not in code (as I had built its layout in Storyboard, alongside some programatic elements). To use the above NavigationLink
, I needed to adjust my UIViewControllerRepresentable
as such;
struct CameraControllerWrapper: UIViewControllerRepresentable {
typealias UIViewControllerType = CameraController
func makeUIViewController(context: UIViewControllerRepresentableContext<CameraControllerWrapper>) -> CameraControllerWrapper.UIViewControllerType {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController: CameraController = mainStoryboard.instantiateViewController(withIdentifier: "CameraController") as! CameraController
return mainViewController
}
func updateUIViewController(_ uiViewController: CameraControllerWrapper.UIViewControllerType, context: UIViewControllerRepresentableContext<CameraControllerWrapper>) {
//
}
}
A few potential optimizations for @ZbadhabitZ answer, for people who may be relatively new to Swift, starting with a brief example.
extension NotesVC : UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> NotesVC {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "NotesVC")
return vc as! NotesVC
}
func updateUIViewController(_ vc: NotesVC, context: Context) {
// your stuff here
}
}
Function arguments with the heavy typing are overkill; or confusing, at least.
Apple Developer demo shows an example with PageViewController that shows all the extra typing isn't necessary:
The original answer's code doesn't make use of Swift implied types. For example, rather
let flag: Bool = false
Instead write:
let flag = false
flag
will be typed as Bool
implicitly in that declaration. That is because false
always implies Bool
. Just as 1.0
always implies Double
by default, and so on. The payoff gets even bigger when you start getting into longer class names.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.