Ios 在关闭动画之前运行UIAlertController完成处理程序块

Ios 在关闭动画之前运行UIAlertController完成处理程序块,ios,swift,cocoa-touch,uialertcontroller,Ios,Swift,Cocoa Touch,Uialertcontroller,我正在使用UIAlertController设置一个非常标准的操作表,如下所示: let alert = UIAlertController(title: "title", message: nil, preferredStyle: .actionSheet) alert.addAction( UIAlertAction(tit

我正在使用
UIAlertController
设置一个非常标准的操作表,如下所示:

    let alert = UIAlertController(title: "title",
                                  message: nil,
                                  preferredStyle: .actionSheet)

    alert.addAction(
        UIAlertAction(title: "button",
                      style: .default,
                      handler: { _ in
                        MediaPlayer.playSound(.click)
                        // The above line just uses AVAudioPlayer to play
                        // an MP3 file. Its implementation isn't relevant
                        // to the question and can be assumed to be correct.
    }))
当我按下按钮时,警报解除,然后完成处理程序运行并播放声音。由于警报的解除动画需要一段时间,在我按下按钮和声音播放之间有一个非常明显的延迟;当声音开始时,警报甚至不再可见

是否有一种方法可以在按下按钮后立即播放声音,而不必等到关闭动画完成


此外,有没有理由不容易做到这一点?也就是说,苹果反对人们在提醒按钮上添加点击声音吗?

基本上你对此无能为力。一旦UIAlertController替换了UIAlertView,用户点击和按钮操作处理程序运行之间的延迟就很明显:

实际上,你正在尝试做苹果公司不希望你做的事情,即,将声音与警报控制器按钮相关联


我的解决方案很简单:不要使用UIAlertController。构建一个定制的呈现视图控制器非常简单,它看起来就像UIAlertController的视图,实际上UIAlertController就是一个呈现视图控制器。那就自己滚吧。现在该按钮是您的了,您可以检测到点击并发出声音响应,然后关闭,没问题。

与其像Matt建议的那样重建
UIAlertController
(并在每次调整时更新它以匹配iOS),不如简单地将其子类化。您可以给它一个代码块,在它消失时运行它。例如:

class CustomAlertController: UIAlertController {
    var onDisappear: (() -> Void)?

    override func viewWillDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        onDisappear?()
    }
}
然后,可以在显示警报控制器之前设置此块:

let controller = CustomAlertController(title: "Title", message: nil, preferredStyle: .actionSheet)
controller.onDisappear = {
    // play sound here
}

不,调用警报操作处理程序时无法更改。因此,当用户点击警报按钮时,基本上不可能播放声音?可能是这样。点击按钮后,处理器不会在纳秒级运行。它是告诉你警报已经解除,并告诉你哪个按钮被点击了。