Adding UIAlertView's show() functionality to UIAlertController.
Have you ever needed to present an alert without knowing the visible view controller? In case you're drawing a blank, let me give an example.
Assume we have an app in the App Store and we want to let the users know there is an update. How would we do that?
AppDelegate.swift
func applicationDidBecomeActive(application: UIApplication) {
if update {
UIAlertView(title: "Update Available", message: "Would you like to update your app?", delegate: self, cancelButtonTitle: "Yes!").show()
}
}
Easy, right? We don't have to worry about which view controller is visible. UIAlertView seems to find the visible view controller and add itself as a subview.
UIAlertView and system alerts might actually use their own UIWindow just like DBAlertController, but I digress.
AppDelegate.swift
func applicationDidBecomeActive(application: UIApplication) {
if update {
let alertController = UIAlertController(title: "Update Available", message: "Would you like to update your app?", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "Yes!", style: .Default, handler: nil))
window!.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
}
}
This will work... but only if the rootViewController's view is in the window hierarchy.
What if the rootViewController's view is not in the window hierarchy?
- The UIAlertController does not appear.
- You get a warning message written to your console. Something like:
015-05-13 08:09:58.923 DBAlertController[1002:15635] Warning: Attempt to present <UIAlertController: 0x7ff5f2e3a500> on <UINavigationController: 0x7ff5f2f24760> whose view is not in the window hierarchy!
There's a demo of this scenario in the source. Pull it down and try it yourself.
DBAlertController fixes the issue above by presenting the UIAlertController on its own UIWindow.
Add pod 'DBAlertController'
to your Podfile.
Add github "dbettermann/DBAlertController"
to your Cartfile.
Copy and paste DBAlertController.swift into your project.
let alertController = DBAlertController(title: "DBAlertController", message: "Hello World!", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
alertController.show()
Here is the full signature for show()
:
func show(animated flag: Bool = true, completion: (() -> Void)? = nil)
As you can see, you can also pass an animated flag and completion closure that get passed along to
presentViewController(alertController, animated: flag, completion: completion)
All feedback is welcome. Tweet at me or send me an email with any questions, comments, or issues.