导致 UIViewControllerRepresentable 目标的多个 NavigationLinks 最终以空白屏幕结束
Multiple NavigationLinks leading to UIViewControllerRepresentable destination ends up with blank screen
我发现了一个存在错误的最小 SwiftUI 应用程序:
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())
)
)
}
}
}
重现步骤:
- 点击“详细信息屏幕”
- 点击“查看 UIKit VC”。您将看到“Hello, World”UIViewController。
- 点击返回
- 点击“查看 UIKit VC”
预期:
- 您应该再次看到“Hello, World”UIViewController
实际:
- 您将看到一个空白视图。只要您尝试,这种情况就会发生很多次。
注意:在注释掉的代码中,如果您只有一层深度的 NavigationLink,它可以正常工作。
您没有正确使用 UIViewControllerRepresentable
。您需要在 makeUIViewController
中创建一个新的视图控制器,在您的案例中重复使用它会破坏视图控制器的生命周期。
UIViewControllerRepresentable
属性可以在创建或更新视图控制器时传递给它,如下所示:
struct ViewControllerContainer: UIViewControllerRepresentable {
let props: Int
func makeUIViewController(context: Context) -> some UIViewController {
HelloWorldVC(props: props)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
uiViewController.props = props
}
}
我发现了一个存在错误的最小 SwiftUI 应用程序:
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())
)
)
}
}
}
重现步骤:
- 点击“详细信息屏幕”
- 点击“查看 UIKit VC”。您将看到“Hello, World”UIViewController。
- 点击返回
- 点击“查看 UIKit VC”
预期:
- 您应该再次看到“Hello, World”UIViewController
实际:
- 您将看到一个空白视图。只要您尝试,这种情况就会发生很多次。
注意:在注释掉的代码中,如果您只有一层深度的 NavigationLink,它可以正常工作。
您没有正确使用 UIViewControllerRepresentable
。您需要在 makeUIViewController
中创建一个新的视图控制器,在您的案例中重复使用它会破坏视图控制器的生命周期。
UIViewControllerRepresentable
属性可以在创建或更新视图控制器时传递给它,如下所示:
struct ViewControllerContainer: UIViewControllerRepresentable {
let props: Int
func makeUIViewController(context: Context) -> some UIViewController {
HelloWorldVC(props: props)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
uiViewController.props = props
}
}