You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI视图中使用UIKit显示弹窗及实现交互的问题求助

SwiftUI中UIKit弹窗的两个问题解决方案

问题1:让UIKit弹窗在屏幕居中显示

你的代码当前无法正确弹出弹窗,且UIAlertController默认就是屏幕居中布局,只需修正弹窗的调用与展示逻辑即可:

  1. 修正TestView的弹窗触发方式:通过@State变量控制弹窗状态,将UIAlertViewPopup作为子视图嵌入当前视图层级
  2. 在UIAlertViewPopup的updateUIViewController方法中,处理弹窗的弹出与消失逻辑,确保从当前活跃窗口的根控制器present弹窗

修改后的核心代码:

public struct TestView: View {
    @State var show = false

    public var body: some View {
        Button{
            show = true
        } label {
            Text("tap me")
        }
        .background(UIAlertViewPopup(show: $show, title: "test", message: "test", onEditProfile: {
            // 这里可临时写测试逻辑
            print("编辑个人资料")
        }))
    }
}
struct UIAlertViewPopup: UIViewControllerRepresentable {
    typealias UIViewControllerType = UIAlertController
    
    @Binding var show: Bool
    var title: String
    var message: String
    var onEditProfile: () -> Void

    func makeUIViewController(context: Context) -> UIAlertController {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        
        let cancelAction = UIAlertAction(title: "Cancel", style: .destructive) { _ in
            show = false
        }
        
        let submitAction = UIAlertAction(title: "Edit profile", style: .default) { _ in
            show = false
            onEditProfile()
        }
        
        alert.addAction(cancelAction)
        alert.addAction(submitAction)
        
        return alert
    }

    func updateUIViewController(_ uiViewController: UIAlertController, context: Context) {
        // 获取当前活跃窗口的根控制器
        guard let rootVC = UIApplication.shared.connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .compactMap({$0 as? UIWindowScene})
            .first?.windows
            .first(where: {$0.isKeyWindow})?.rootViewController else { return }
        
        if show, rootVC.presentedViewController == nil {
            rootVC.present(uiViewController, animated: true)
        } else if !show {
            uiViewController.dismiss(animated: true)
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject {
        var control: UIAlertViewPopup
        init(_ control: UIAlertViewPopup) {
            self.control = control
        }
    }
}

说明:UIAlertController本身就是系统默认居中的弹窗组件,只要通过正确的控制器present,就能自动居中显示。


问题2:点击「Edit profile」按钮调用指定函数

通过给UIAlertViewPopup添加闭包参数onEditProfile,在弹窗的按钮回调中触发这个闭包,即可实现外部传递指定函数的需求:

  1. 在UIAlertViewPopup中新增var onEditProfile: () -> Void参数
  2. 点击「Edit profile」时调用onEditProfile()
  3. 在TestView中传递需要执行的函数(可以是内联闭包,也可以是外部定义的函数)

示例:

// 外部定义的指定函数
func handleEditProfile() {
    print("执行编辑个人资料逻辑")
    // 这里添加你的业务代码,比如跳转编辑页面、提交修改等
}

// 在TestView中使用
public struct TestView: View {
    @State var show = false

    public var body: some View {
        Button{
            show = true
        } label {
            Text("tap me")
        }
        .background(UIAlertViewPopup(show: $show, title: "test", message: "test", onEditProfile: handleEditProfile))
    }
}

内容的提问来源于stack exchange,提问作者stefanosn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 15:55:20