I have found a minimal SwiftUI app that exhibits a bug:
class HelloWorldVC: UIViewController {
override func loadView() {
super.loadView()
let label = UILabel()
label.text = "Hello, World"
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
}
struct ViewControllerContainer: UIViewControllerRepresentable {
let vc: UIViewController
func makeUIViewController(context: Context) -> some UIViewController { vc }
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}
struct ContentView: View {
var body: some View {
NavigationView {
// Works:
//NavigationLink("View UIKit VC", destination: ViewControllerContainer(vc: HelloWorldVC()))
// Only loads the UIKit view once. It's blank on subsequent tries.
NavigationLink(
"Detail Screen",
destination: NavigationLink(
"View UIKit VC",
destination: ViewControllerContainer(vc: HelloWorldVC())
)
)
}
}
}
Expected:
Actual:
Note: In the commented out code, it works properly if you only have one layer deep of NavigationLink.
You are not working with UIViewControllerRepresentable
correctly. You need to create a new view controller inside makeUIViewController
, reusing it breaks the view controller lifecycle in your case.
The UIViewControllerRepresentable
properties can be passed to the view controller when you create or update it, as follows:
struct ViewControllerContainer: UIViewControllerRepresentable {
let props: Int
func makeUIViewController(context: Context) -> some UIViewController {
HelloWorldVC(props: props)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
uiViewController.props = props
}
}