Anton Tropashko Anton Tropashko - 5 months ago 15
Swift Question

Alert that can work on iOS 7 and iOS 8

I'm getting dyld: Symbol not found: _OBJC_CLASS_$_UIAlertAction
when I'm trying to get this monstrosity to run.

How do I weaklink 8.0 stuff?

var device : UIDevice = UIDevice.currentDevice()!;
var systemVersion = device.systemVersion;
var iosVerion : Float = systemVersion.bridgeToObjectiveC().floatValue;
if(iosVerion < 8.0) {
let alert = UIAlertView()
alert.title = "Noop"
alert.message = "Nothing to verify"
alert.addButtonWithTitle("Click")
alert.show()
} else {
var alert : UIAlertController? = UIAlertController(title: "Noop", message: "Nothing to verify", preferredStyle: UIAlertControllerStyle.Alert)
if alert {
let actionStyle : UIAlertActionStyle? = UIAlertActionStyle.Default;
var alertAction : UIAlertAction? = UIAlertAction(title: "Click", style: actionStyle!, handler: nil)
if(alertAction) {
alert!.addAction(alertAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
return;


Resolved: UIKit had to be marked Optional rather than Required. Simplified version is now:

var device : UIDevice = UIDevice.currentDevice()!;
var systemVersion = device.systemVersion;
var iosVerion : Float = systemVersion.bridgeToObjectiveC().floatValue;
if(iosVerion < 8.0) {
let alert = UIAlertView()
alert.title = "Noop"
alert.message = "Nothing to verify"
alert.addButtonWithTitle("Click")
alert.show()
} else {
var alert : UIAlertController = UIAlertController(title: "Noop", message: "Nothing to verify", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Click", style:.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}

Answer
  • Explicitly add UIKit in the "Link Binary With Libraries" section of your project's build phases.

  • You can test for the existence of UIAlertController like this:

    if NSClassFromString("UIAlertController") != nil {
        // Use it
    } else {
        // Fall back
    }
    
  • I wrote a wrapper that works on both iOS 7 and iOS 8. You can find it here. It takes a view controller followed by a bunch of optional arguments and any number of buttons:

    showAlert(self, style: .ActionSheet, sourceView: cell, completion: {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    },
        (.Default, "Send clipboard", {
            if someCondition {
                // completion must be specified because of a Swift bug (rdar://18041904)
                showAlert(self, title: "Nothing to send", message: "The clipboard is empty.", completion: nil,
                    (.Cancel, "OK", nil)
                )
            }
        }),
        (.Cancel, "Cancel", nil)
    )