• Skip to main content

AndyBargh.com

Exploring the World of Swift and iOS Development

  • Contact
  • Swift Developments
    • Back Issues
  • Blog
    • Latest Articles
You are here: Home / Swift / UIAlertController

UIAlertController

posted on 28th October 2015

UIAlertController

In this post, I thought I’d take a look at the UIAlertController class, a class introduced by Apple in iOS 8 as a replacement for the traditional UIAlertView and UIActionSheet classes.

As such, the UIAlertController class provides a unified mechanism for displaying alerts across the system that wraps up both modal and popover alert display into a single more flexible interface.

In this post, we’re going to build a sample application that contains two buttons, one that will display an action sheet when tapped and one that will display a modal alert.

During the course of the example application, we’ll look at the different styles of action that can be attached to these alerts and also look at the additional control and flexibility that the UIAlertController brings.

Table of Contents

  • Setup Example Project
  • Setup the User Interface
  • UIAlertController
  • Displaying an Action Sheet
  • Troubleshooting the Action Sheet
  • Displaying an Alert
  • Adding Text Fields
  • Conditionally Enabling Actions
  • Programatically Dismissing the UIAlertController

Setup Example Project

To kick things off, let’s start by creating a new demo application.

Open up Xcode and create a new project using the Single View Application template.

Enter UIAlertController for the project name and select Swift for the language. Leave the device set to Universal and then select the Next button.

When prompted, choose where to save your project (if you’re just experimenting your Desktop is a good option) and then select the Create button.

Setup the User Interface

With the new project created, select the Main.storyboard file in the project browser. Ensure the Object Library is displayed by pressing ⌃⌥⌘ (or by selecting View > Utilities > Show Object Library).

In the search field of the Object Library, enter Button and from the filtered list drag a UIButton instance onto the view positioning the button towards the top of the view using the layout guides.

Once positioned, double-click on the button and set the button title to Show Alert. This will be the button that will, as you might have guessed, display a modal alert when tapped.

With the button still selected, click on the Resolve Auto Layout Issues button toward the bottom right of the Interface Builder window (I’ve highlighted the button with red circle in the picture below) and then select the Add missing constraints button to setup any missing constraints for the button and make sure it stays in place at runtime.

Next, bring up the assistant editor by pressing on the icon towards the top-right of the Xcode window (or by pressing ⌥⌘ or selecting View > Assistant Editor > Show Assistant Editor).

Make sure the Assistant Editor is showing the ViewController.swift file.

With the button selected in the storyboard, press ⌥⌘6 (or select View > Utilities > Show Connections Inspector from the Xcode menus) to bring up the Connections Inspector.

Click and drag from the Touch Up Inside connector in the Connections Inspector down to the code in the assistant editor to create a new IBAction.

Release the mouse and when prompted, enter showAlert for the function name and change the type to UIButton before selecting the Connect button.

With the modal alert button created, we now need to create a second button to display an action sheet. The process is basically identical.

Drag a second button onto the user interface from the Object Library and position it just below the first. Use the guides to line it up centrally in the view before double-clicking on the button and changing its title to Show Action Sheet.

With the button still selected, select the Resolve Auto Layout Issues button (or select Editor > Resolve Auto Layout Issues) and then select Add Missing Constraints. This will add any missing constraints for the new button.

From the Connections Inspector drag from the Touch Up Inside connector down to the ViewController.swift file in the counterpart view. (Press ⌥⌘6 or View > Utilities > Show Connections Inspector if the Connections Inspector is not displayed).

When prompted, enter showActionSheet for the function name, change the type to UIButton and press the Connect button.

UIAlertController

If you’ve ever used the UIAlertView and UIActionSheet classes prior to iOS 8, the interface to the UIAlertController is a little different.

There used to be a lot of quirks and inconsistencies with the UIAlertView and UIActionSheet classes which have been eliminated with the UIAlertController class. Things have also been simplified. We no longer have to use delegate protocols such as the UIActionSheetDelegate or UIAlertViewDelegate protocols to configure the alerts, instead everything is encapsulated within the UIAlertController class itself along with a number of closures we can provide to configure its behaviour.

Let’s dive in then and start looking at what we can actually do with the UIAlertController class. We’ll start with something simple: How to display an action sheet.

Displaying an Action Sheet

If it is still open, close the Assistant Editor and open the Standard Editor by pressing ⌘ (or by selecting View > Standard Editor > Show Standard Editor from the menu). Next, select the ViewController.swift file in the project browser to bring the file up in the main Xcode editor.

Change the showActionSheet function to the following. We’ll walk through what it is doing afterwards.

@IBAction func showActionSheet(sender: UIButton) {
        
        // 1.
        // Create and initialize a UIAlertController instance.
        //
        let alertController = UIAlertController(title: "Your Title",
            message: "Your Message",
            preferredStyle: .ActionSheet)
        
        // 2.
        // Initialize the actions to show along with the alert.
        //
        let destructiveAction = UIAlertAction(title:"Destroy", 
            style: .Destructive) { (action) -> Void in 
                print("You selected the Destructive action") 
        }

        let defaultAction = UIAlertAction(title:"Default",
            style: .Default) { (action) -> Void in
                print("You selected the Default action")
        }
        
        let cancelAction = UIAlertAction(title:"Cancel",
            style: .Cancel) { (action) -> Void in
                print("You selected the Cancel action")
        }
        
        // 3.
        // Tell the alertController about the actions we want it
        // to present.
        // 
        alertController.addAction(destructiveAction)
        alertController.addAction(defaultAction)
        alertController.addAction(cancelAction)
        
        // 4.
        // Present the alert controller and associated actions.
        // 
        self.presentViewController(alertController,
            animated: true, completion: nil)
    }

There are four main steps to creating and displaying an action sheet using the UIAlertController class and we’ll walk through it step by step.

First up, we need to create and initialise an instance of the UIAlertController class.

As part of the initialisation, the UIAlertController class accepts a title and message that will be displayed as part of the alert. The third parameter to the initialiser is the preferredStyle. This configures whether the alert controller will be displayed as an action sheet (UIAlertControllerStyle.ActionSheet or .ActionSheet for short) or as a modal alert (UIAlertControllerStyle.Alert or .Alert for short). When configured as an .ActionSheet the views of the UIAlertController are anchored to the bottom of the presenting view. When configured as .Alert they are presented as model alert, centred within the presenting view controller. In this case, I’ve set the preferred style to .ActionSheet as we want to display an action sheet.

Next, we setup the possible actions that the user can take when the UIAlertController is presented. These take the form of instances of the UIAlertAction class.

The initialiser for the UIAlertAction class accepts a title, a style (of type UIAlertActionStyle and an associated closure that will be executed should the action be selected by the user. The title is the title that will be displayed for the action when the alert is displayed on screen. The style parameter configures the style of the action. There are three styles to choose from:
– Default which applies the default style to the button.
– Destructive which indicates that the action may change or delete data.
– Cancel which applies a style indicating that the action cancels things and data will remain unchanged.

It should be noted that you can only ever have a single action configured with the Cancel style in any given alert though. If you try to have more than one, you’ll get a runtime exception.

In this code I’m creating one action with each of the three different styles so you can see what they look like when we run our app.

In addition to the title and style parameter, the initialiser for the UIAlertAction class also accepts a closure that has a UIAlertAction as its single argument. In each case, the statements within the closure will be executed should the user select the associated action. To keep things simple for now, I’ve configured the closures to print a simple statement to the console indicating which action was selected.

With all the UIAlertAction instances created, the next thing we do is add the actions to the alertController we created.

Adding actions to the UIAlertController is done in a specific order as the order we add the actions governs the order that they will be displayed when presented. The only exceptions to this is are that any action configured with the .Cancel style, will be displayed last, regardless of the order in which it was added and the The Apple Human Interface Guidelines also recommends that you add any actions with the .Destructive style first so try to keep this in mind when you’re adding actions of your own.

That’s pretty much it though. With all the alert actions added, all that is left is to display the alert itself.

To do this we use the the presentViewController(_:animated:completion:) method, passing in the alert controller instance we created. We also pass in true to animate presentation of the alert controller and nil for the third argument as we don’t need to be informed when the animation completes.

At this point you should be able to run the app in the simulator and see what it looks like.

At this point, only the Show Action Sheet button will work. Tap on the button and you should see the alert displayed as an action sheet along with the various actions and their styles. If at this point you tap on any of the actions, the action sheet will disappear and you should see a message appear in the console window indicating which action you selected.

Troubleshooting the Action Sheet

If at this point you don’t see the same output as me there are a couple of things you might need to check.

Firstly, go back through the code and make sure that you’ve covered all the steps. The most likely thing to have happen if things aren’t working is that you’ve missed connecting the button in the storyboard up to the associated IBAction code in the ViewController.swift file. Go back and check that the connection is correct by selecting the button in the storyboard and checking the connections for the button in the Connections Inspector. Make sure the Touch Up Inside event is wired up to the showActionSheet method in the ViewController.swift file. If you’re still struggling, drop me a message in the comment form below.

Next we’ll look at how to display a modal alert.

Displaying an Alert

The code to display a modal alert with the UIAlertController is almost identical to that of displaying an action sheet. The only real difference is the fact that we set the preferredStyle parameter of the AlertController to be .ActionSheet instead of .Alert. Change the showAlert function to the following:

@IBAction func showAlert(sender: UIButton) {
        
        // 5.
        // Create and initialize a UIAlertController instance.
        //
        let alertController = UIAlertController(title: "Login",
            message: "Enter your details",
            preferredStyle: .Alert)
        
        // 6.
        // Initialize the actions to show along with the alert.
        // 
        let submitAction = UIAlertAction(title:"Submit",
            style: .Default) { (action) -> Void in
                print("You selected the submit action.")
        }
        
        let cancelAction = UIAlertAction(title:"Cancel",
            style: .Cancel) { (action) -> Void in
                print("You selected the Cancel action")
        }

        // 7.
        // Tell the alertController about the actions we want it to present.
        //
        alertController.addAction(submitAction)
        alertController.addAction(cancelAction)
        
        // 8.
        // Present the alert controller and associated actions.
        //
        self.presentViewController(alertController,
            animated: true, completion: nil)
    }

As you can see, the code’s a little different (we’re going to extend it in the next section) but the general structure is identical to what we saw with the action sheet. In this case, we create a UIAlertController instance initialising it with a title and message but set the preferred style to .Alert rather than .ActionSheet. In the next couple of lines, we then create two actions, a Submit action and a Cancel action which we then add to the UIAlertController instance. In the final line, we then present our UIAlertController instance.

At this point, you can re-run the app. This time the Show Alert button should be working so if you tap the Show Alert button you should see the UIAlertController displayed as a modal alert.

As with the action sheet, tapping on any of the buttons will dismiss the alert and should display a message in the console window indicating which of the actions you tapped.

Adding Text Fields

Now, this is where things get interesting. The UIAlertController gives us some additional features beyond the original UIAlertView that you might be used to. One of these features is the ability to add multiple text fields to the UIAlertController that will be displayed within the alert when it is presented. When displayed, the text fields are stacked and displayed in the order that they are added to the UIAlertController.

There is a word of caution here though. These additional text fields are supported only when the UIAlertController style is set to .Alert. If you try to add text fields to the UIAlertController when its style is set to .ActionSheet you’ll get a runtime exception. You’ve been warned.

Let’s see if we can extend our modal alert functionality to add a couple of text fields.

Back in Xcode, add the following code to the showAlert function just below where we created the cancelAction.

// 9.
// Add text fields to the alert and configure.
// 
alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
      textField.placeholder = "Username"
}
        
alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
      textField.placeholder = "Password"
      textField.secureTextEntry = true
}

In this code, I’m creating two text fields using the addTextFieldWithConfigurationHandler:_ function on the UIAlertController.

The addTextFieldWithConfigurationHandler:_ method accepts a single parameter which is a closure that accepts a single UITextField parameter. The closure will be called by the UIAlertController once it has created a UITextField instance on our behalf and within the closure we get a chance to configure the properties of the text field.

For the first text field, the one that will accept a username, we do just that, simply setting the placeholder text for the text field. We also do this for the second text field, but in this case we also configure the text field for secure text entry as this field will be used to capture the users password.

With the text fields configured, next let’s modify the closure for the submitAction to print out the contents of the two text fields when the user taps the submit button.

Add the following code to the submitAction closure, just below the existing print statement.

// 10.
// Print the text from the username and password
// text fields when the submit button is pressed.
//
if let usernameTextField = alertController.textFields?.first,
    let username = usernameTextField.text,
    let passwordTextField = alertController.textFields?.last,
    let password = passwordTextField.text {
    print("Username: \(username), Password: \(password)")
}

At first glance this code might look a bit daunting but lets walk through it step by step.

What we’re primarily doing here is making use of Swifts ability to bind multiple optionals in a single line. Any text fields that have been added to the UIAlertController instance are held as an optional array textFields are held in the same order as were added to the UIAlertController. The property is an optional however as no text fields may have been added so we first need to unwrap the array to access its contents.

As we added the username text field to the UIAlertController first, we initially unwrap the textfields property and access the first text field in the array optionally binding it to the usernameTextField constant. We then use that in the second binding to access the text in from that text field, binding that text to a second constant username. With the content of the first text field extracted, we then repeat this process in the next two bindings extracting the password text field from the textFields property followed by the text from that text field. In this case we bind them to the passwordTextField and password constants respectively. With everything extracted successfully, within the if statement, we simply print the username and password to the console using the print function.

At this point we can re-run the application. This time when you tap the Show Alert button, you should see a modal alert containing the two text fields we just created.

Enter some text in the username and password fields. Notice that the password field has the standard secure text entry format due to the configuration we setup within the closure.

As previously, if you tap the Submit action, the alert will disappear but this time the username and password you entered will be printed in the console.

This is great, but it doesn’t really make sense to be able to submit an empty username and password though. Ideally, we’d only enable the Submit action once the user has entered at least some text for the username and password. Let’s see if we can fix that.

Conditionally Enabling Actions

So what do we need to do? Well first, we need to start off with the Submit action being disabled when the alert is first presented to the user. To do this, we can simply set the enabled property of the Submit action to false.

Add the following code to the showAlert function just after where we created the two actions.

// 11.
// Initially disable the submit action.  We'll enable it later
// when the user has entered text in both a username and password
// text fields.
//
submitAction.enabled = false

Next, we’ll further modify the two closures associated with the addTextFieldWithConfigurationHandler functions.

Here, we’ll set the text fields to call a new callback function (alertTextFieldDidChange:) whenever the text in either of the two text fields changes (the EditingChanged event).

Add the following code to the end of each of the two closures:

// 12.
// Add a callback to the `alertTextFieldDidChange:` function that
// is triggered when the text in the text field changes.
//
textField.addTarget(self, action: "alertTextFieldDidChange:",
    forControlEvents: .EditingChanged)

With the callbacks setup, the next thing to do is add the alertTextFieldDidChange: callback function otherwise the app will crash. Add the following new function to the ViewController class:

// 14.
// Check the text in both the username and password text fields.  If they both have
// some text, enable the submit button otherwise disable it.
//
func alertTextFieldDidChange(sender : UITextField) {

    guard let alertController = self.presentedViewController as? UIAlertController,
    let username = alertController.textFields?.first?.text,
    let password = alertController.textFields?.last?.text,
    let submitAction = alertController.actions.first else {
        return
    }

    submitAction.enabled = username.characters.count > 0 &&
        password.characters.count > 0
}

Lets have a look at what it’s doing.

First I’m using the new guard statement available in Swift 2.0. The guard condition allows us to check for certain conditions and forces the function to return if the conditions are not met. In this case, I’m also combining it with the multi-optional-binding we saw earlier. When we combine the guard statement with optional binding in this way any of the bindings that were successful are available throughout the remainder of the scope in which the guard statement was called but after the closing brace of the guard statement. In this case, were doing this with four different constants.

First we get hold of the UIAlertController instance binding this to a new local constant called alertController. If that binding was successful we then use optional chaining to access the username and password text fields for the alert controller and extract their associated text, optionally binding the values to the local constants username and password respectively.

As I mentioned previously the text fields held in a local array property textfields on UIActionController instance and are stored in the same order as when we added them so using that fact we can use the first and last properties of the array to get hold of the username and password text fields respectively.

If these were also successful, we then move onto the final binding, where we bind the Submit action from the alert controllers actions array to a new local constant called submitAction. As with the text fields, the actions are held in an array in the order that they were added so we can simply use the first property of the array to get hold of the Submit action.

Wow. That was a lot of bindings!

Anyway, if any of the bindings fail, within the body of the guard statement, we return as per the requirements of the guard statement. If however, all these bindings went well we set the enabled state of the Submit action. We do this by setting it to true if both the username and password entered by the user contain at least one character and false otherwise.

Re-run the application and check out the new functionality.

If you run the app now, you should see the Submit action start off disabled. If you then enter some text you should notice that the Submit action is only enabled if both the username and password fields contain some text. Great job! Before I wrap up though, there’s one final thing I want to cover.

Programatically Dismissing the UIAlertController

The final thing I wanted to do before closing out this article is look at how we can dismiss an UIAlertController instance programatically. Typically, the UIAlertController instance is dismissed automatically when the user taps one of the actions, you’ve seen this already, but there are some scenarios such as when your application moves into the background that require us to dismiss the UIAlertController instance programatically rather than having it dismissed by the user. The good news is that this is relatively simple to do.

Lets start out by getting the ViewController to observe when the application moves into the background. We can do this by registering with the NSNotificationCenter singleton and a observing the UIApplicationDidEnterBackground notification.

In the viewDidLoad function of the ViewController class add the following code:

// 15.
// Register the view controller as an observer of the UIApplicationDidEnterBackgroundNotification
// event and hook it up to the didEnterBackground: callback method.
// 
NSNotificationCenter.defaultCenter().addObserver(self,
    selector: "didEnterBackground:", 
    name: UIApplicationDidEnterBackgroundNotification, 
    object: nil)

All this does is setup the ViewController class as an observer of the UIApplicationDidEnterBackground event, and sets it up to call the didEnterBackground: function on the ViewController when the event occurs.

Whilst we’re here, we had also better de-register ourselves as well.

The best place to do this is in the deinit function for the class.

Add the following new code below the viewDidLoad function:

deinit {
    // perform the deinitialization

    // 16. 
    // Remove the view controller as an observer of the UIApplicationDidEnterBackgroundNotification 
    // event. 
    //
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

All we do here is call the removeObserver(observer:) function on the default NSNotificationCenter instance passing in the ViewController instance for the observer parameter. This removes the ViewController instance as an observer from all notifications posted by the notification centre.

So we’ve set things up to call the didEnterBackground function when the notification occurs, the next thing we’d better do is write the callback function.

Add the following new function to the ViewController class.

// 17.
// The callback method that is called when the UIApplicationDidEnterBackgroundNotification
// notification is posted. When called, programatically dismiss the UIAlertController if it
// has been presented.
//
func didEnterBackground(notification : NSNotification) {
    self.presentedViewController?.dismissViewControllerAnimated(false, completion: nil)
}

As you can see, the code is only a single line. All it does is call the dismissViewControllerAnimated(flag:completion:) function on the presented view controller (if it is presented). In this case the presented view controller is our UIViewController instance.

That’s all there is to it.

All that’s left to do then is to check out our new functionality.

Run up the application again and tap the Show Alert button. As expected, you should see the UIAlertController displayed as an alert. This time though, instead of entering text or selecting either of the actions, press the home button (⇧⌘H or Hardware > Home if your running in the simulator). This will put the app into the background. As a final step, bring the app back to the foreground by tapping on its icon. You should see that the UIAlertController instance has been dismissed. Mission accomplished!

Well done if you made it this far! It’s a much longer post than I expected but it’s covered most of the functionality of UIAlertController.

If you need additional information, check out Apple documentation on the UIAlertController and UIAlertAction classes.

Filed Under: Swift, UIKit Tagged With: Action, Action Sheet, Alert, Background, NSNotificationCenter, Swift, UIAlertController, UIAlertView, UIKit

  • About
  • Terms of Service
  • Privacy Policy
  • Contact

Copyright © 2025 · Academy Pro on Genesis Framework · WordPress · Log in

AndyBargh.com uses cookies to understand how you use our site and to serve you personalized content and ads. By continuing to use this site, you accept these cookies, our privacy policy and terms of service.Ok