How To: Displaying Alerts With UIAlertController In Swift

Written by Reinder de Vries on October 24 2017 in App Development

How To: Displaying Interactive Alerts With UIAlertController In Swift

In this article, you’ll learn how to use the UIAlertController class to display alert dialogs to the user of your iOS app. We’ll dive into setting up the alerts, responding to user actions, and getting input from the user with text fields.

The UIAlertController is a basic but important part of the iOS SDK, and it’s the default way to ask users to confirm an action. On top of that, UIAlertController also supports the action sheet – a convenient dialog style that allows your app’s users to quickly take action.

This article is specially written for beginner iOS developers. Working with the UIAlertController is a fundamental topic for practical iOS developers.

Ready? Let’s go.

  1. Displaying Alerts With UIAlertViewController
  2. UIAlertController Styles: Alert Or Action Sheet?
  3. Responding To UIAlertController With Actions
  4. Accepting User Input With Text Fields
  5. Further Reading

Displaying Alerts With UIAlertViewController

Are you sure? You’ve probably seen dozens of alert dialogs in iOS, Android, on the web, and on your Mac. Alert dialogs are as old as computers themselves! (Before computers had GUIs, you’d type “Y” or “N” at the command-line.)

Here’s an iOS alert dialog:

UIAlertController alert example

Alerts are crucial when building your app, to ask the user for confirmation of a sensitive action. Deleting data, signing out, giving permission, confirming a change – they are all tasks that your app’s user better think twice about before continuing.

As you can see in the example alert above, alerts help with grouping similar actions together and presenting them as one. Do you want to make a backup before erasing? Do you want to pay with PayPal or checkout with your creditcard? Do you want to take this incoming call or send an “I’ll call you later” message?

Most alerts can’t be dismissed without taking an action, and that’s why they’re so effective. When an alert is presented, it fills the entire iPhone screen. You can’t move away without making a choice. Such an alert is known as a modal dialog. On iOS, they’re simply called alerts.

As a design rule, you should always have a Cancel option that dismisses the alert and reverts the app to its previous state.

So… enough user interaction talk. Let’s check out how you can create an alert with UIAlertController!

Here’s an example:

let alert = UIAlertController(title: "Did you bring your towel?", message: "It's recommended you bring your towel before continuing.", preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))

self.present(alert, animated: true)

What’s happening here?

  • First, you’re creating a constant called alert and assigning it an instance of UIAlertController. The constructor of UIAlertController takes three arguments: a title, a description and an alert controller style.
  • Then, you’re adding two actions to the alert: Yes and No. More on actions later.
  • Finally, you’re presenting the alert by calling the function present(_:animated:) on self. This will display the alert to the user.

Here’s how that example code looks in your app:

Using the UIAlertViewController constructor is pretty straightforward. You provide a title and message as strings, and then choose an alert type from the UIAlertControllerStyle enumeration.

You always have to “present” an alert, to show it to the user. Presenting a UIAlertController can only be done on a currently visible view controller that’s part of the view controller stack. Unless you’re doing something crazy, it’s most likely that you’re presenting the dialog from an active view controller.

Learn how to build iOS apps

Get started with iOS 12 and Swift 4

Sign up for our iOS development course Zero to App Store and learn how to build professional iOS 12 apps with Swift 4 and Xcode 10.

UIAlertController Styles: Alert Or Action Sheet?

When creating your alert controller, you can choose between two options:

  • A simple alert, with the .alert constant
  • An action sheet, with the .actionSheet constant

Here’s what that exact same alert looks like, with both options:

UIAlertController style options actionsheet alert

Action sheets are pretty cool. They have three benefits over alerts:

  • They slide up from the bottom of the iPhone screen, so you can reach the action sheet buttons with your thumb. Easy!
  • You can fit more text on the button, compared to the alert style.
  • Usually, you need less text than an alert, because the action sheet buttons are self-explanatory.

When should you use an alert, and when an action sheet?

I think it’s best to use an action sheet for choosing between multiple similar options, like “Choose from Photo Library” and “Take Picture with Camera”.

When you need explicit confirmation on a positive and negative action, like “Yes” and “No”, or “OK” and “Cancel”, I think it’s best to use an alert style dialog.

It’s fairly typical for action sheets to not display a title or message to the user. Instead, you let the options speak for themselves. When you present a user with an action sheet, always give them the option to get out of the action sheet with a Cancel button.

Fun Fact: Prior to iOS 8, you would use the UIAlertView class to display alerts, and the UIActionSheet to display action sheets. You’d use the typical iOS target-action mechanism to respond to user interaction. Since then, those classes have been merged, and actions now take closures to respond to a user’s tap.

Responding To UIAlertController With Actions

With UIAlertController provides you with a mechanism to respond to user interaction. When a user taps an action you’ve attached to your alert, it calls a closure you’ve associated with that alert.

Like this:

alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: { action in
    print("Yay! You brought your towel!")
}))

When you deconstruct the above example code, you’ll find this:

  • You can add actions to an alert with the addAction(_:) function. It takes one argument, an instance of UIAlertAction.
  • You can construct an UIAlertAction with a title, a style and a handler. The handler is a closure, and the style is a constant from the enum UIAlertActionStyle.

Within the closure you can define what happens when the action is executed, i.e. what happens when the user taps the alert button. In the above code, this is the closure that’s executed:

{ action in
    print("Yay! You brought your towel!")
}

As you can see, the closure has one parameter action of type UIAlertAction. It’s a reference to the action that’s invoked and it allows you to distinguish between actions, for instance when you use one closure for multiple actions.

Actions can have three styles:

  • Default, with the constant .default
  • Cancel, with the constant .cancel
  • Destructive, with the constant .destructive

By default, the .cancel action is highlighted in the alert. You can see that in the example images above. The cancel option is effectively biased, which means you’ll have to make a conscious effort to confirm an alert. This means you’re less likely to make a mistake!

The .destructive style is usually red, indicating to your app’s users that this is a dangerous action or one that cannot be undone.

Note: Even if you change the order of adding the actions to the alert, the Cancel button is always shown first.

The UIAlertController can also have a preferred action. When specified, the alert then highlights that action. By default, the cancel button is the preferred action. You can also assign an action yourself, but you’ll first have to add it with the addAction(_:) function before assigning it to the preferredAction property of UIAlertController.

Accepting User Input With Text Fields

One last thing…

You can also add a text field to an alert. Like this:

let alert = UIAlertController(title: "What's your name?", message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

alert.addTextField(configurationHandler: { textField in
    textField.placeholder = "Input your name here..."
})

alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in

    if let name = alert.textFields?.first?.text {
        print("Your name: \(name)")
    }
}))

self.present(alert, animated: true)

In the above code sample, this happens:

  • First, you create an UIAlertController instance with type .alert.
  • Then, you’re adding a simple Cancel action.
  • Then, you’re adding a text field with the addTextField(configurationHandler:) function. You can use the closure to configure the text field, like setting the placeholder property. When you want to use the input from the text field, you have to use one of the actions.
  • Finally, you’re adding an action that says OK. When this action is invoked, the input from the text field is printed out to the debugger with print. You can access the text field by using the textFields array on the alert.

And here’s what it looks like in your app:

UIAlertController text field

Pretty neat, right? This effectively turns the alert into a prompt you can use to quickly ask for user input.

Learn how to build iOS apps

Get started with iOS 12 and Swift 4

Sign up for our iOS development course Zero to App Store and learn how to build professional iOS 12 apps with Swift 4 and Xcode 10.

Further Reading

And that’s all there is to using alerts! You now know how to create one, how to configure it, how to respond to user actions, and why it’s sometimes better to use an action sheet than an alert dialog. Awesome!

Got a question? Leave it in the comments, below.

Want to learn more? Check out these resources:

Reinder de Vries

Reinder de Vries is a professional iOS developer. He teaches app developers how to build their own apps at LearnAppMaking.com. Since 2009 he has developed a few dozen apps for iOS, worked for global brands and lead development at several startups. When he’s not coding, he enjoys strong espresso and traveling.

Leave a Reply

Required to post: Your real name and email address, and a pleasant demeanor. Your email address will not be published. Markdown is supported.

  • Ahmed Gaghamin July 10, 2018 15:31

    You Rock!
    I just want to thank you for taking the time to offer us your help in Swift Coding, that takes a lot of time and effort.

    May God bless.

    Right on.

    1. Reinder de Vries July 10, 2018 17:22 in reply to Ahmed

      Thank you! That's great to hear, and I'm glad I could help.

  • Hi Reinder,

    Firstly, very helpful posts so thank you for that.

    Secondly, how can we trigger the alert when a new view controller is loaded?

    I've tried putting it in viewDidLoad in a fresh project and keep getting the same error of:
    "2018-06-10 16:56:22.493921+1000 TestOne[11023:6034989] Warning: Attempt to present on <TestOne.ViewController: 0x1052102c0> whose view is not in the window hierarchy!"

    I've tried using apple's example from here with the same result: https://developer.apple.com/documentation/uikit/uialertcontroller?changes=_4

    I've also tried viewDidAppear and viewDidLoad but that didn't work.

    Any suggestions would be greatly appreciated.

    Thanks in advance.

    1. Reinder de Vries June 10, 2018 13:39 in reply to David

      Thank you! And a good question.

      When viewDidLoad() is called, the view has been loaded, but it hasn't been added to the view hierarchy yet. That's why you see that error! The earliest point you can hook into is viewDidAppear(). These functions are part of the view controller lifecycle.

      I've just tested with a fresh project, and I can present an alert controller from viewDidAppear(). Like this:

      override func viewDidAppear(_ animated: Bool)
      {
          super.viewDidAppear(animated)
      
          let alert = UIAlertController(title: "DON'T PANIC!", message: "The quick brown fox jumps over the lazy dog.", preferredStyle: .alert)
          alert.addAction(UIAlertAction(title: "Okay", style: .default, handler: nil))
          self.present(alert, animated: true)
      }
      

      You will need to make that call to super.viewDidAppear(animated). If you still see an error in your own app, make sure that the view itself is actually part of the view hierarchy!

      1. David June 11, 2018 00:58 in reply to Reinder

        Awesome! Thank you Reinder.

        Yes that worked straight away.

        Much appreciated.
        Regards,
        David

  • Eric Wilson May 13, 2018 02:13

    I am looking for a way to interrupt a video queue by having the user tap the screen to then supply questions, like: should we skip this part, should we cancel the entire queue, should we back up to the first part, should we increase the foreground volume, should we decrease the background volume, etc. etc. Does the alert offer any flexibility for these custom features. I'm probably barking up the wrong tree. If so, can you suggest some class or other tools to use ?

    1. Reinder de Vries May 13, 2018 09:32 in reply to Eric

      Hmm. The UIAlertController is just a UI component, so it doesn't contain much controlling logic. You probably have to write the controller code for this yourself, i.e. the code that makes the decisions to present an alert dialog based on events. You could trigger those with the timestamps of the video, for instance. You can work with video and audio using the AVFoundation framework.

      Keep in mind that alert dialogs are presented modally, i.e. they fill the entire screen and "block" everything behind the dialog. If that's an unwanted video experience, you could design something like a tooltip that pops out of the video controls whenever you need the user's input on something. Good luck!

  • Thanks for tut! I just needed a small reference.

    1. Reinder de Vries April 27, 2018 22:35 in reply to Jose

      Awesome! Glad you like it :-)

  • The tutorial was awesome. Thanks.

  • Ali Martins March 3, 2018 16:03

    Ty for the tutorial. I have a question.
    I noticed that the UIAlert happen assynchronous, i.e. the code doesnt stop. How do I pause the code until the User presses a button on the UIAlert?

    1. Reinder de Vries March 3, 2018 16:26 in reply to Ali

      Hmm, it doesn't really work like that. You can respond when the user taps an alert button by creating an action, but you can't pause the code. Read a bit about how asynchronous code works, and how you structure it. Also learn how to work with closures and GCD. This is a good start: https://learnappmaking.com/grand-central-dispatch-swift-3/

  • Umut Dönmez February 4, 2018 14:34

    Ty for this tutorial. Good job

  • Jamil Bin Hossain November 11, 2017 10:08

    Nice illustrations !!

    1. Reinder de Vries November 11, 2017 11:01 in reply to Jamil

      Thanks! Glad you like 'em.