iOS14中UIHostingController嵌套的SwiftUI视图无法弹出Alert的解决办法?
iOS14中UIHostingController嵌套SwiftUI视图的Alert不显示解决方案
在iOS14环境下,嵌套在UIKit的UIHostingController中的SwiftUI视图使用.alert(isPresented:)无法弹出弹窗,本质原因是iOS14的UIHostingController未正确传递presentationMode环境值,导致SwiftUI内置的Alert依赖的弹出逻辑失效。以下是几种可行的解决办法:
方法1:手动注入presentationMode环境值
在创建UIHostingController时,给SwiftUI根视图手动注入presentationMode环境变量,确保Alert能获取到正确的弹出上下文:
// 创建SwiftUI视图 let contentView = ContentView() // 初始化HostingController let hostingController = UIHostingController(rootView: contentView) // 手动注入presentationMode环境值 let presentationMode = PresentationMode( dismiss: { hostingController.dismiss(animated: true) } ) hostingController.rootView = hostingController.rootView .environment(\.presentationMode, .init(wrappedValue: presentationMode))
方法2:通过闭包回调到UIKit层弹出Alert
在SwiftUI视图中定义回调闭包,将弹出Alert的逻辑交给外层的UIKit控制器处理,完全绕过SwiftUI的Alert限制:
修改SwiftUI视图
struct ContentView: View { // 定义弹出Alert的回调闭包 let showAlert: () -> Void var body: some View { VStack { Button("Delete") { showAlert() } Spacer() }.padding() } }
在UIKit层处理弹出
// 创建ContentView时传入回调 let contentView = ContentView { [weak self] in guard let self = self else { return } let alert = UIAlertController(title: "Are you sure?", message: nil, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) self.present(alert, animated: true) } // 初始化HostingController let hostingController = UIHostingController(rootView: contentView)
方法3:封装UIKit的UIAlertController为SwiftUI组件
自定义一个UIViewControllerRepresentable组件,封装UIKit的UIAlertController,在SwiftUI视图中直接使用,兼容iOS14及以上版本:
封装UIKitAlert组件
struct UIKitAlert: UIViewControllerRepresentable { @Binding var isPresented: Bool let title: String func makeUIViewController(context: Context) -> UIAlertController { let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in isPresented = false }) return alert } func updateUIViewController(_ uiViewController: UIAlertController, context: Context) { // 根据isPresented状态控制弹窗的显示/隐藏 if isPresented, uiViewController.presentingViewController == nil { context.coordinator.parent?.present(uiViewController, animated: true) } else if !isPresented, uiViewController.presentingViewController != nil { uiViewController.dismiss(animated: true) } } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject { weak var parent: UIViewController? let alert: UIKitAlert init(_ alert: UIKitAlert) { self.alert = alert super.init() } override func didMoveToParent(_ parent: UIViewController?) { self.parent = parent } } }
在SwiftUI视图中使用
struct ContentView: View { @State private var presentAlert = false var body: some View { VStack { Button("Delete") { presentAlert = true } Spacer() } .padding() // 添加封装的UIKitAlert组件 .background(UIKitAlert(isPresented: $presentAlert, title: "Are you sure?")) } }
内容的提问来源于stack exchange,提问作者andrew
相关产品推荐
相关产品推荐

