Dismissal of UIAlertController (best practice)
Asked Answered
L

3

15

When using UIAlertController like this:

var alert = UIAlertController(title: "Core Location", 
     message: "Location Services Disabled!", 
     preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, 
     handler: nil))
self.navigationController.presentViewController(alert, animated: true, 
     completion: nil)

I noticed that the dismissal of the alert view is seemingly done automatically. Shouldn't the dismissal of a presented ViewController be done by the presenting ViewController via a delegate call?

Lindsylindy answered 17/8, 2014 at 12:56 Comment(0)
W
3

The dismissal is "included" in the presentViewController call. You do not need a delegate because you have the completion block. In this block you put what you would normally put into the delegate callback, except the call to dismiss the alert.

As far as "best practice" is concerned, I noted that in many APIs, Apple replaced delegate callbacks with completion blocks. Apple typically recommends using the block syntax. I surmise this could be partly because it helps keeping the related code sections together.

Winifred answered 17/8, 2014 at 13:16 Comment(7)
Thanks - so we no longer need delegates for dismissing modal ViewControllers? - where is the dismissal call included?Lindsylindy
It does not have to be done explicitly. When you press a button on the alert, it is dismissed automatically.Winifred
This answer can be read to imply that the completion closure of the presentViewController:animated:completion method is invoked when the alert is dismissed. If you read it that way, be warned that this is not the case. As the docs say: "The completion handler is called after the viewDidAppear: method is called on the presented view controller". i.e. it has nothing to do with dismissalChrisse
No, the completion argument of this method is for a "callback" after the animation presenting the view controller has finished. This makes sense - a non-modal view controller could stay up indefinitely. I agree that this could be confusing, but note that the parameter is not called "completion" but "handler", indicating that there is this important difference.Winifred
#30840735. Any Help with that please?Bale
In iOS 9 (and probably iOS 8 too), the completion block to -presentViewController:animated:completion: is executed just after the UIAlertController first appears. If you need a callback for when the user dismisses the alert controller, then provide a UIAlertAction whose type is UIAlertActionStyleCancel, and put your code in that object's handler. It will execute when the alert controller is dismissed by tapping outside of the popover or tapping the cancel button.Newsom
First, the answer itself is not related to the topic. I think that guy is asking, why the design UIAlertController is so special that it aim to dismiss by itself. I think he definitely know, the normal way of UIViewController life cycle and management. I think you can talk more about how UIAlertController differentiate from the other and why it is. BTW the completion block of presentViewController(_:UIViewController, _:Bool, _:Void->()) is not designed to be call when a vc is "dismissed"(I guess you might mix up the usage of "the presenting vc is going to be dismiss" something )Pigheaded
S
4

Is some Cases you may like to use this:

  class MyAlertController : UIAlertController {
    var dismissHandler : (()->())?
    override func viewDidDisappear(_ animated: Bool) {
      dismissHandler?()
      super.viewDidDisappear(animated)
    }
  }

Usage:

  let alert = MyAlertController(title: ...
  let cancelButton = UIAlertAction(titl
  alert.dismissHandler = { /*...do something */ }
  alert.addAction(cancelButton)
  ...
Salpingectomy answered 30/10, 2020 at 17:7 Comment(0)
W
3

The dismissal is "included" in the presentViewController call. You do not need a delegate because you have the completion block. In this block you put what you would normally put into the delegate callback, except the call to dismiss the alert.

As far as "best practice" is concerned, I noted that in many APIs, Apple replaced delegate callbacks with completion blocks. Apple typically recommends using the block syntax. I surmise this could be partly because it helps keeping the related code sections together.

Winifred answered 17/8, 2014 at 13:16 Comment(7)
Thanks - so we no longer need delegates for dismissing modal ViewControllers? - where is the dismissal call included?Lindsylindy
It does not have to be done explicitly. When you press a button on the alert, it is dismissed automatically.Winifred
This answer can be read to imply that the completion closure of the presentViewController:animated:completion method is invoked when the alert is dismissed. If you read it that way, be warned that this is not the case. As the docs say: "The completion handler is called after the viewDidAppear: method is called on the presented view controller". i.e. it has nothing to do with dismissalChrisse
No, the completion argument of this method is for a "callback" after the animation presenting the view controller has finished. This makes sense - a non-modal view controller could stay up indefinitely. I agree that this could be confusing, but note that the parameter is not called "completion" but "handler", indicating that there is this important difference.Winifred
#30840735. Any Help with that please?Bale
In iOS 9 (and probably iOS 8 too), the completion block to -presentViewController:animated:completion: is executed just after the UIAlertController first appears. If you need a callback for when the user dismisses the alert controller, then provide a UIAlertAction whose type is UIAlertActionStyleCancel, and put your code in that object's handler. It will execute when the alert controller is dismissed by tapping outside of the popover or tapping the cancel button.Newsom
First, the answer itself is not related to the topic. I think that guy is asking, why the design UIAlertController is so special that it aim to dismiss by itself. I think he definitely know, the normal way of UIViewController life cycle and management. I think you can talk more about how UIAlertController differentiate from the other and why it is. BTW the completion block of presentViewController(_:UIViewController, _:Bool, _:Void->()) is not designed to be call when a vc is "dismissed"(I guess you might mix up the usage of "the presenting vc is going to be dismiss" something )Pigheaded
A
1

There is an elegant way! Just write the action or function inside the alert controller's cancel action. (here the action style should be .cancel)

Code for Swift 3:

let Alert: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)

    let OkAction: UIAlertAction = UIAlertAction(title: “Ok”, style: .default) { ACTION in

       //Will be called when tapping Ok

    }

    let CancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) {ACTION in

      // Will be called when cancel tapped or when alert dismissed.
      // Write your action/function here if you want to do something after alert got dismissed”

    }

    Alert.addAction(OkAction)
    Alert.addAction(CancelAction)

present(Alert, animated: true, completion: nil)
Aer answered 29/8, 2018 at 12:3 Comment(1)
If you want to do something on dismissal, you have to add it to every action because, for example, tapping OK also dismisses the alert.Mildamilde

© 2022 - 2024 — McMap. All rights reserved.