3

I am trying (...) to add a sound effect to the buttons added to a UIAlertController. I fire a sound effect in the handler, but this actually is a bit too late. The sound fires like 0.5 seconds too late. I want the sound to fire as soon as the alert is about to dismiss, not after it has dismissed. With UIAlertView this was possible to handle using alertWillDismiss... rather than alertDidDismiss.

Did I miss something?

Jonny
  • 15,955
  • 18
  • 111
  • 232
  • Related http://stackoverflow.com/questions/32441856/uialertaction-handler-running-after-delay?rq=1 – Jonny Feb 17 '16 at 03:38
  • If you think you have a good use case, do file a bug report with Apple! – matt Feb 17 '16 at 03:40
  • I tried to log in to bugreport.apple.com but all I got was **An error has occurred. For assistance accessing Apple Bug Reporter, please contact Apple Developer Program Support.** I guess I'm being hated, generally. Or all of us are. – Jonny Feb 17 '16 at 03:43
  • I'm figuring they didn't add this feature because of this problem: http://stackoverflow.com/questions/25932589/concurrent-uialertcontrollers - the handler wouldn't be able to open another uialertcontroller if the previous one isn't completely dismissed yet - if using the same uiviewcontroller to open both alerts. Just my assumptions. – Jonny Feb 19 '16 at 03:13

3 Answers3

3

No, you didn't miss anything. The functionality you're looking for is not provided by UIAlertController. Consider providing your own presented view controller, over which you'll have the kind of fine control you're after.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Worth noting that it might be easy to subclass UIAlertController and override viewWillDisappear, but this class may become final in the future – Patrick Goley Feb 17 '16 at 03:40
2

I used Patrick Goley's suggestion, namely to subclass UIAlertController and override viewWillDisappear. Worked great for me.

//
//  ImmediateClickAlertController.swift
//
//  This subclass of UIAlertController plays a click immediately whenever it is dismissed (i.e. when a button is tapped).
//  This fixes an issue when trying to play a click in an attached UIAlertAction, which does not happen until after its view disappears.

import AudioToolbox

class ImmediateClickAlertController: UIAlertController {

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        // play a click
        let pressKeySystemSoundID: SystemSoundID = 1104
        AudioServicesPlaySystemSound(pressKeySystemSoundID)
    }
}
Charlie Hitchcock
  • 287
  • 1
  • 3
  • 8
-1

A bit of a hackery, but perhaps you could:

  1. Try and grab a reference to the alert's button (by traversing the -admittedly private- view hierarchy tree), and
  2. Use KVO to detect any changes to its selected and/or highlighted properties (my own experience is that selected is not reliably observable, while highlighted is).

...but all of this is quite fragile, not elegant, maight break in a future release of the OS and/or get you rejected from the app store...?

So you're best option (even if the most laborious) is to roll your own modal view controller:

Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189