So it turns out that because AnyObject is the spiritual successor to id, you can call any message you want on AnyObject. That's the equivalent of sending a message to id. Ok, fair enough. But now we add in the concept that all methods are optional on AnyObject, and we have something we can work with.
Given the above, I was hopeful I could just cast UIApplication.sharedApplication() to AnyObject, then create a variable equal to the method signature, set that variable to the optional method, then test the variable. This didn't seem to work. My guess is that when compiled against the iOS 8.0 SDK, the compiler knows where it thinks that method should be, so it optimizes this all down to a memory lookup. Everything works fine until I try to test the variable, at which point I get a EXC_BAD_ACCESS.
However, in the same WWDC talk where I found the gem about all methods being optional, they use Optional Chaining to call an optional method - and this seems to work. The lame part is that you have to actually attempt to call the method in order to know if it exists, which in the case of registering for notifications is a problem because you're trying to figure out if this method exists before you go creating a UIUserNotificationSettings object. It seems like calling that method with nil though is okay, so the solution that seems to be working for me is:
var ao: AnyObject = UIApplication.sharedApplication()
if let x:Void = ao.registerUserNotificationSettings?(nil) {
// It's iOS 8
var types = UIUserNotificationType.Badge | UIUserNotificationType.Sound | UIUserNotificationType.Alert
var settings = UIUserNotificationSettings(forTypes: types, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
} else {
// It's older
var types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound | UIRemoteNotificationType.Alert
UIApplication.sharedApplication().registerForRemoteNotificationTypes(types)
}
After much searching related to this, the key info came from this WWDC talk https://developer.apple.com/videos/wwdc/2014/#407 right in the middle at the section about "Optional Methods in Protocols"
In Xcode 6.1 beta the above code does not work anymore, the code below works:
if UIApplication.sharedApplication().respondsToSelector("registerUserNotificationSettings:") {
// It's iOS 8
var types = UIUserNotificationType.Badge | UIUserNotificationType.Sound | UIUserNotificationType.Alert
var settings = UIUserNotificationSettings(forTypes: types, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
} else {
// It's older
var types = UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound | UIRemoteNotificationType.Alert
UIApplication.sharedApplication().registerForRemoteNotificationTypes(types)
}