UIAlertView/UIAlertController iOS 7 and iOS 8 compatibility

Shan picture Shan · Aug 4, 2014 · Viewed 52.1k times · Source

I am using Swift to write an app and I need to show an alert. The app must be iOS 7 and iOS 8 compatible. Since UIAlertView has been replaced with UIAlertController, how can I check if the UIAlertController is available without checking the system version? I have been hearing that Apple recommends that we should not check the system version of the device in order to determine the availability of an API.

This is what I am using for iOS 8 but this crashes on iOS 7 with "dyld: Symbol not found: _OBJC_CLASS_$_UIAlertAction" :

let alert = UIAlertController(title: "Error", message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
presentViewController(alert, animated: true, completion: nil)

If I use the UIAlertView for iOS 8, I get this warning: Warning: Attempt to dismiss from view controller <_UIAlertShimPresentingViewController: 0x7bf72d60> while a presentation or dismiss is in progress!

Answer

Warren Burton picture Warren Burton · Aug 17, 2014

The detection pattern is identical to the Objective-C style.

You need to detect whether the current active runtime has the ability to instantiate this class

if objc_getClass("UIAlertController") != nil {

     println("UIAlertController can be instantiated")

      //make and use a UIAlertController

 }
 else {

      println("UIAlertController can NOT be instantiated")

      //make and use a UIAlertView
}

Don't try and work out this based on the OS version. You need to detect abilities NOT OS.

EDIT

The original detector for this answer NSClassFromString("UIAlertController") fails under -O optimisation so its been changed to the current version which does work for Release builds

EDIT 2

NSClassFromString is working at all optimisations in Xcode 6.3/Swift 1.2