我使用 UIViewControllerRepresentable
创建了这个非常简单的包装器:
struct ViewControllerWrapperView: UIViewControllerRepresentable {
let controller: UIViewController
func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerWrapperView>) -> UIViewController {
return controller
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ViewControllerWrapperView>) {}
}
使用它在 SwiftUI View 中显示 ViewController 效果很好:
struct ContentView: View {
@State private var viewSwitch: Bool = true
let blueView: ViewControllerWrapperView = {
let blueViewController = UIViewController()
blueViewController.view.backgroundColor = .blue
return ViewControllerWrapperView(controller: blueViewController)
}()
let redView: ViewControllerWrapperView = {
let redViewController = UIViewController()
redViewController.view.backgroundColor = .red
return ViewControllerWrapperView(controller: redViewController)
}()
var body: some View {
Button("Switch") { viewSwitch.toggle() }
if viewSwitch {
blueView
} else {
redView
}
}
}
但是一旦我将 ViewControllerWrapperView
包装在 AnyView
中,它们就会停止正常工作:
struct ContentView: View {
@State private var viewSwitch: Bool = true
let blueView: AnyView = {
let blueViewController = UIViewController()
blueViewController.view.backgroundColor = .blue
return AnyView(ViewControllerWrapperView(controller: blueViewController))
}()
let redView: AnyView = {
let redViewController = UIViewController()
redViewController.view.backgroundColor = .red
return AnyView(ViewControllerWrapperView(controller: redViewController))
}()
var body: some View {
Button("Switch") { viewSwitch.toggle() }
if viewSwitch {
blueView
} else {
redView
}
}
}
使用AnyView
,点击按钮时 View 不会切换。更深入地研究一下,我发现了以下内容:
对于首次显示 View 时的两种情况:
- 在蓝色 View 的
ViewControllerWrapperView
上调用makeUIViewController
。 updateUIViewController
在蓝色 View 的ViewControllerWrapperView
上调用,参数uiViewController
是蓝色 ViewController。
现在,如果没有 AnyView
,当点击切换按钮时,UIViewControllerRepresentable
的生命周期将按预期执行:
updateUIViewController
在蓝色 View 的ViewControllerWrapperView
上调用,参数uiViewController
是蓝色 ViewController。- 在红色 View 的
ViewControllerWrapperView
上调用makeUIViewController
。 - 在红色 View 的
ViewControllerWrapperView
上调用updateUIViewController
,参数uiViewController
是红色ViewController。 dismantleUIViewController
被调用,参数uiViewController
是蓝色 View 。
但是使用AnyView
,当点击切换按钮时,唯一发生的事情是:
updateUIViewController
在 RED View 的ViewControllerWrapperView
上调用,参数uiViewController
是 蓝色 View Controller 。
我是否遗漏了什么,或者这是 SwiftUI 中的一个错误?
最佳答案
Am I missing something or is this a bug in SwiftUI?
这不是一个错误,AnyView
消除了类型差异,因此渲染 body
SwiftUI 引擎只会看到 AnyView
替换为 AnyView
相等,因此引擎不会替换现有 View ,而只是刷新它(因为状态已更改),从而导致 updateUIViewController
调用。一切都如预期。
这就是为什么使用 AnyView
应该非常非常小心和有意义,并清楚地了解过程和后果。
关于ios - UIViewControllerRepresentable 包装在 AnyView 中时无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73151408/