UIViewRepresentable能否承载SwiftUI视图?还是应使用UIViewControllerRepresentable?
UIViewRepresentable能否承载SwiftUI视图?还是应使用UIViewControllerRepresentable?
嘿,我之前也见过有人用UIViewRepresentable配合UIHostingController来承载SwiftUI视图的写法,就像下面这段示例代码那样:
struct SwiftUIHostView: UIViewRepresentable { let content: () -> any View func makeUIView(context: Context) -> UIView { let hostingVC = UIHostingController(rootView: content()) let hostView = hostingVC.view! hostView.translatesAutoresizingMaskIntoConstraints = false return hostView } func updateUIView(_ uiView: UIView, context: Context) { // 这里可能会尝试更新内部的SwiftUI视图,但逻辑容易出问题 } }
这种写法看起来能跑起来,但我得跟你说——这其实是不符合Apple设计规范的不推荐做法,原因有这么几点:
- 首先得搞清楚两个协议的定位:
UIViewRepresentable是专门用来封装单个独立UIKit视图的,而UIHostingController本质是个视图控制器,对应的封装协议应该是UIViewControllerRepresentable,用错类型等于违背了Apple的设计初衷。 - 其次会丢生命周期管理:
UIHostingController自带一套完整的视图控制器生命周期回调,比如viewWillAppear、viewDidDisappear这些,直接把它的view抽出来塞给UIViewRepresentable,这些生命周期事件大概率不会正常触发,时间长了容易导致SwiftUI视图的状态混乱、动画失效,甚至出现内存泄漏。 - 最后是维护成本问题:其他开发者看到这种“非常规”写法会一脸懵,遇到bug排查起来也比常规写法麻烦得多。
那正确的姿势应该是怎样的?直接用UIViewControllerRepresentable来封装UIHostingController就对了,比如下面的示例:
struct SwiftUIHostController: UIViewControllerRepresentable { let content: () -> any View func makeUIViewController(context: Context) -> UIHostingController<AnyView> { UIHostingController(rootView: AnyView(content())) } func updateUIViewController(_ uiViewController: UIHostingController<AnyView>, context: Context) { // 这里可以安全地更新根视图 uiViewController.rootView = AnyView(content()) } }
简单来说:临时跑起来的写法不代表正确,遵循Apple的设计规范用UIViewControllerRepresentable来承载SwiftUI视图,才是能避免后续各种坑的靠谱选择。
内容来源于stack exchange
相关产品推荐
相关产品推荐

