Did you know that UIAlert View and UIAction Sheet (as well as their respective delegate protocols) are deprecated in iOS 8?

It’s true. ⌘-click on UIAlert View or UIAction Sheet in your code, and check out the top-level comment:

UIAlert View is deprecated. Use UIAlert Controller with a preferred Style of UIAlert Controller Style Alert instead.

Wondering why Xcode didn’t alert you to this change? Just read down to the next line:

@availability ( i OS , introduced = 2.0 )

Although these classes are technically deprecated, this is not communicated in the @availability attribute. This should be of little surprise, though; UIAlert View has always played it fast and loose.

From its very inception, UIAlert View has been laden with vulgar concessions, sacrificing formality and correctness for the whims of an eager developer audience. Its delegate protocol conformance was commented out of its initializer ( delegate:(id /* <UIAlert View Delegate> */)delegate ). And what protocol methods that did exist triggered when a button At Index: “clicked” rather than “tapped”. This, and trailing variable-length arguments for other Button Titles , awkward management of button indexes, a -show method with no regard for the view hierarchy… the list goes on.

UIAction Sheet was nearly as bad, though developers can’t be bothered to remember what the heck that control is called half the time, much less complain about its awkward parts.

As such, the introduction of UIAlert Controller should be met like an army liberating a city from occupation. Not only does it improve on the miserable APIs of its predecessors, but it carves a path forward to deal with the UIKit interface singularity brought on by the latest class of devices.

This week’s article takes a look at UIAlert Controller , showing first how to port existing alert behavior, and then how this behavior can be extended.

UIAlert Controller replaces both UIAlert View and UIAction Sheet , thereby unifying the concept of alerts across the system, whether presented modally or in a popover.

Unlike the classes it replaces, UIAlert Controller is a subclass of UIView Controller . As such, alerts now benefit from the configurable functionality provided with view controller presentation.

UIAlert Controller is initialized with a title , message , and whether it prefers to be displayed as an alert or action sheet. Alert views are presented modally in the center of their presenting view controllers, whereas action sheets are anchored to the bottom. Alerts can have both buttons and text fields, while action sheets only support buttons.

Rather than specifying all of an alert’s buttons in an initializer, instances of a new class, UIAlert Action , are added after the fact. Refactoring the API in this way allows for greater control over the number, type, and order of buttons. It also does away with the delegate pattern favored by UIAlert View & UIAction Sheet in favor of much more convenient completion handlers.

Comparing the Old and New Ways to Alerts

A Standard Alert

The Old Way: UIAlertView

let alert View = UIAlert View ( title : "Default Style" , message : "A standard alert." , delegate : self , cancel Button Title : "Cancel" , other Button Titles : "OK" ) alert View . alert View Style = . Default alert View . show () // MARK: UIAlert View Delegate func alert View ( alert View : UIAlert View , clicked Button At Index button Index : Int ) { switch button Index { … } }

The New Way: UIAlertController

let alert Controller = UIAlert Controller ( title : "Default Style" , message : "A standard alert." , preferred Style : . Alert ) let cancel Action = UIAlert Action ( title : "Cancel" , style : . Cancel ) { ( action ) in … } alert Controller . add Action ( cancel Action ) let OKAction = UIAlert Action ( title : "OK" , style : . Default ) { ( action ) in … } alert Controller . add Action ( OKAction ) self . present View Controller ( alert Controller , animated : true ) { … }

A Standard Action Sheet

UIActionSheet

let action Sheet = UIAction Sheet ( title : "Takes the appearance of the bottom bar if specified; otherwise, same as UIAction Sheet Style Default." , delegate : self , cancel Button Title : "Cancel" , destructive Button Title : "Destroy" , other Button Titles : "OK" ) action Sheet . action Sheet Style = . Default action Sheet . show In View ( self . view ) // MARK: UIAction Sheet Delegate func action Sheet ( action Sheet : UIAction Sheet , clicked Button At Index button Index : Int ) { switch button Index { ... } }

UIAlertController

let alert Controller = UIAlert Controller ( title : nil , message : "Takes the appearance of the bottom bar if specified; otherwise, same as UIAction Sheet Style Default." , preferred Style : . Action Sheet ) let cancel Action = UIAlert Action ( title : "Cancel" , style : . Cancel ) { ( action ) in … } alert Controller . add Action ( cancel Action ) let OKAction = UIAlert Action ( title : "OK" , style : . Default ) { ( action ) in … } alert Controller . add Action ( OKAction ) let destroy Action = UIAlert Action ( title : "Destroy" , style : . Destructive ) { ( action ) in println ( action ) } alert Controller . add Action ( destroy Action ) self . present View Controller ( alert Controller , animated : true ) { … }

New Functionality

UIAlert Controller is not just a cleanup of pre-existing APIs, it’s a generalization of them. Previously, one was constrained to whatever presets were provided (swizzling in additional functionality at their own risk). With UIAlert Controller , it’s possible to do a lot more out-of-the-box:

Alert with Destructive Button

The type of an action is specified by UIAlert Action Style , which has three values:

.Default : Apply the default style to the action’s button.

: Apply the default style to the action’s button. .Cancel : Apply a style that indicates the action cancels the operation and leaves things unchanged.

: Apply a style that indicates the action cancels the operation and leaves things unchanged. .Destructive : Apply a style that indicates the action might change or delete data.

So, to add a destructive action to a modal alert, just add a UIAlert Action with style .Destructive :

let alert Controller = UIAlert Controller ( title : "Title" , message : "Message" , preferred Style : . Alert ) let cancel Action = UIAlert Action ( title : "Cancel" , style : . Cancel ) { ( action ) in println ( action ) } alert Controller . add Action ( cancel Action ) let destroy Action = UIAlert Action ( title : "Destroy" , style : . Destructive ) { ( action ) in println ( action ) } alert Controller . add Action ( destroy Action ) self . present View Controller ( alert Controller , animated : true ) { … }

Alert with >2 Buttons

With one or two actions, buttons in an alert are stacked horizontally. Any more than that, though, and it takes on a display characteristic closer to an action sheet:

let one Action = UIAlert Action ( title : "One" , style : . Default ) { ( _ ) in } let two Action = UIAlert Action ( title : "Two" , style : . Default ) { ( _ ) in } let three Action = UIAlert Action ( title : "Three" , style : . Default ) { ( _ ) in } let cancel Action = UIAlert Action ( title : "Cancel" , style : . Cancel ) { ( _ ) in } alert Controller . add Action ( one Action ) alert Controller . add Action ( two Action ) alert Controller . add Action ( three Action ) alert Controller . add Action ( cancel Action )

Creating a Login Form

iOS 5 added the alert View Style property to UIAlert View , which exposed much sought-after private APIs that allowed login and password fields to be displayed in an alert, as seen in several built-in system apps.

In iOS 8, UIAlert Controller can add text fields with the add Text Field With Configuration Handler method:

let login Action = UIAlert Action ( title : "Login" , style : . Default ) { ( _ ) in let login Text Field = alert Controller . text Fields ! [ 0 ] as UIText Field let password Text Field = alert Controller . text Fields ! [ 1 ] as UIText Field login ( login Text Field . text , password Text Field . text ) } login Action . enabled = false let forgot Password Action = UIAlert Action ( title : "Forgot Password" , style : . Destructive ) { ( _ ) in } let cancel Action = UIAlert Action ( title : "Cancel" , style : . Cancel ) { ( _ ) in } alert Controller . add Text Field With Configuration Handler { ( text Field ) in text Field . placeholder = "Login" NSNotification Center . default Center () . add Observer For Name ( UIText Field Text Did Change Notification , object : text Field , queue : NSOperation Queue . main Queue ()) { ( notification ) in login Action . enabled = text Field . text != "" } } alert Controller . add Text Field With Configuration Handler { ( text Field ) in text Field . placeholder = "Password" text Field . secure Text Entry = true } alert Controller . add Action ( login Action ) alert Controller . add Action ( forgot Password Action ) alert Controller . add Action ( cancel Action )

Creating a Sign Up Form

UIAlert Controller goes even further to allow any number of text fields, each with the ability to be configured and customized as necessary. This makes it possible to create a fully-functional signup form in a single modal alert:

alert Controller . add Text Field With Configuration Handler { ( text Field ) in text Field . placeholder = "Email" text Field . keyboard Type = . Email Address } alert Controller . add Text Field With Configuration Handler { ( text Field ) in text Field . placeholder = "Password" text Field . secure Text Entry = true } alert Controller . add Text Field With Configuration Handler { ( text Field ) in text Field . placeholder = "Password Confirmation" text Field . secure Text Entry = true }

Though, it must be said, caveat implementor. Just because you can implement a signup form in an alert doesn’t mean you should. Suck it up and use a view controller, like you’re supposed to.

Caveats

Attempting to add a text field to an alert controller with style .Action Sheet will throw the following exception:

Terminating app due to uncaught exception NSInternal Inconsistency Exception , reason: ‘Text fields can only be added to an alert controller of style UIAlert Controller Style Alert ’

Likewise, attempting to add more than one .Cancel action to either an alert or action sheet will raise: