2
votes

I would like to do some actions and present some UI right before and right after any UIAlertController dismisses itself (animation is finished) due to user tapping one of the alert's buttons.

How can I get notified that user pressed some button in my UIAlertController and it is going to be dismissed and then is dismissed?

In docs it is advised against subclassing UIAlertController. I still have tried my luck subclassing, thinking that maybe it internally calls func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) on itself. Something like self.dismiss(..., but it doesn't seem to be the case on iOS10.

I have also tried to add 'manual' dismissing into UIAlertAction handler:

let alert = UIAlertController.init(...
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
    alert.dismiss(animated: true, completion: { 
        print("Dismissed")
    })
})
alert.addAction(defaultAction)

But it seems that alert is dismissed after button press but before calling handler. Anyhow it doesn't work as well. Even if it worked it would be a bit bothersome to remember to add my code into each and every UIAlertAction handler.

I would appreciate any ideas.

1
Why you don't do all needed things inside "defaultAction" block? After this block alert will be dismissed anyway.biloshkurskyi.ss
@biloshkurskyi.ss as I have written in my question - it is error prone, one can easily forget a block somewhere.iur

1 Answers

3
votes

although subclassing is not advised you could use a simple subclass like this:

class CustomAlertController: UIAlertController {

    var willDisappearBlock: ((UIAlertController) -> Void)?
    var didDisappearBlock: ((UIAlertController) -> Void)?

    override func viewWillDisappear(_ animated: Bool) {
        willDisappearBlock?(self)
        super.viewWillDisappear(animated)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        didDisappearBlock?(self)
    }

}

you could then use it like this:

let alert = CustomAlertController(title: "Alert", message: "This is an alert. Press Yes or No.", preferredStyle: .alert)
alert.willDisappearBlock = { alert in
    print("\(alert) will disappear")
}
alert.didDisappearBlock = { alert in
    print("\(alert) did disappear")
}

alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { (yesAction) in
    print("User tapped Yes.")
}))
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (yesAction) in
    print("User tapped No.")
}))
present(alert, animated: true) {
    print("presentCompletion")
}

output is in the following order:

  1. presentCompletion
  2. will disappear
  3. did disappear
  4. User tapped Yes.