如何在UIAlertController消失动画前执行完成处理程序块?
解决UIAlertAction Handler先于消失动画执行的问题
这确实是UIAlertController的默认行为——它会先完成动作表的消失动画,才会调用我们给UIAlertAction设置的handler闭包。要实现点击按钮后先执行你的代码(比如播放点击音效)再让动作表消失,这里有两个可行的方案:
方案一:利用系统通知提前触发代码
UIAlertController会在开始消失动画前发送willDismissNotification通知,我们可以监听这个通知,在通知回调里执行目标代码,这样就能保证代码在消失动画前运行。
示例代码如下:
class YourViewController: UIViewController { // 持有目标动作的引用,用于后续判断 private var targetAction: UIAlertAction? func showActionSheet() { let alert = UIAlertController(title: "title", message: nil, preferredStyle: .actionSheet) // 创建目标动作,handler可以留空或做后续收尾操作 let action = UIAlertAction(title: "button", style: .default) { _ in // 可选:这里可以放动画完成后的收尾逻辑 } alert.addAction(action) self.targetAction = action // 监听willDismiss通知 NotificationCenter.default.addObserver( self, selector: #selector(handleAlertWillDismiss(_:)), name: UIAlertController.willDismissNotification, object: alert ) present(alert, animated: true) } @objc private func handleAlertWillDismiss(_ notification: Notification) { // 判断触发消失的动作是不是我们的目标按钮 if let action = notification.userInfo?[UIAlertControllerActionKey] as? UIAlertAction, action == targetAction { // 在这里执行你需要提前运行的代码 MediaPlayer.playSound(.click) } // 移除观察者,避免内存泄漏 NotificationCenter.default.removeObserver(self, name: UIAlertController.willDismissNotification, object: notification.object) } deinit { // 双重保险,确保观察者被移除 NotificationCenter.default.removeObserver(self) } }
这个方案的优势是完全基于系统API,不需要自定义UI,同时能精准控制只有目标按钮被点击时才触发代码。
方案二:自定义动作表控件
如果你的需求更复杂(比如需要更多自定义交互),可以完全自己实现一个动作表控件。这样你能完全掌控点击按钮后的流程:点击按钮→执行代码→关闭控件,没有系统UIAlertController的限制。
自定义控件可以用UIStackView+UIButton组合,再配合动画实现弹出/消失效果,难度不大,而且能适配更多自定义样式。
补充说明
系统UIAlertController把handler放在消失动画之后执行,是为了保证用户体验的一致性——避免弹窗还在屏幕上时,后续操作的UI变化干扰用户注意力。但如果是播放音效这类无UI的操作,用方案一就能完美解决你的需求。
内容的提问来源于stack exchange,提问作者kmell96
相关产品推荐
相关产品推荐

