如何为UIViewController扩展支持异步等待的简易弹窗方法?
如何为UIViewController扩展支持异步等待的简易弹窗方法?
兄弟,我太懂你想要的效果了——就是能像写同步代码一样,弹个提示框等用户点完确定,再接着执行后面的异步逻辑对吧?你之前的代码报错主要是踩了两个小坑:UIAlertAction的按钮回调是同步闭包,不能直接套async逻辑,而且你用了两个没必要的continuation。咱们来把代码改对:
先上可以直接用的扩展代码:
extension UIViewController { /// 🔔 注意:仅开发调试用!生产环境谨慎使用,continuation处理不当容易引发内存泄漏 func simpleAlert(message: String) async { // 用withCheckedContinuation挂起当前异步任务,直到用户点击按钮 await withCheckedContinuation { continuation in let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) // 给弹窗加确定按钮,点击时恢复挂起的任务 let confirmAction = UIAlertAction(title: "Understood", style: .default) { [weak self] _ in self?.dismiss(animated: true) { // 用户点击按钮后,通知continuation恢复任务 continuation.resume() } } alert.addAction(confirmAction) // 展示弹窗 present(alert, animated: true) } } }
代码逻辑说明:
- 整个方法只需要一个
withCheckedContinuation:它的作用就是把当前的异步任务挂起来,直到我们手动调用continuation.resume() - 按钮的回调是同步闭包,这里完全不需要写async逻辑,只需要在用户点击时触发
resume(),让挂起的代码继续往下走 - 加
[weak self]是为了避免弹窗强引用ViewController导致内存泄漏,哪怕是调试用,尽量规范点总没错 - 弹窗展示完成不需要额外的resume操作,因为我们要等的是用户的点击动作,不是弹窗弹出来的瞬间
调用方式完全符合你的预期:
await simpleAlert(message: "Let's proceed..") await comms.sendInfo() await simpleAlert(message: "Successful! Next step?") await some.process()
再说说你原来代码的错误点:
- 你在UIAlertAction的handler里写了async闭包,但
UIAlertAction的初始化要求handler是(UIAlertAction) -> Void的同步类型,不能是async函数,这就是编译器报“Invalid conversion from 'async' function”的原因 - 你用了两个
withCheckedContinuation,其实完全没必要——我们要等的是用户点击按钮的动作,不是弹窗展示完成的事件
最后再提醒一句:这个方法只适合开发调试时快速实现需求,生产环境如果要做异步弹窗,建议用更安全的方案(比如Combine框架或者自定义回调),避免continuation带来的内存泄漏风险。
内容来源于stack exchange
相关产品推荐
相关产品推荐

