Таким образом, получается, что поскольку AnyObject является духовным преемником идентификатора, вы можете вызвать любое сообщение на AnyObject. Это эквивалентно отправке сообщения на id. Хорошо, достаточно справедливо. Но теперь мы добавляем в концепцию, что все методы в AnyObject являются необязательными , и у нас есть кое-что, с чем мы можем работать.
Учитывая вышесказанное, я надеялся, что смогу просто привести UIApplication.sharedApplication () к AnyObject, затем создать переменную, равную сигнатуре метода, установить эту переменную в необязательный метод, а затем протестировать переменную. Это не похоже на работу. Я предполагаю, что при компиляции с iOS 8.0 SDK компилятор знает, где, по его мнению, должен быть метод , поэтому он оптимизирует все это вплоть до поиска в памяти. Все работает нормально, пока я не попробую проверить переменную, после чего я получу EXC_BAD_ACCESS.
Тем не менее, в том же докладе WWDC, где я нашел жемчужину о том, что все методы являются необязательными, они используют Optional Chaining для вызова необязательного метода - и это, похоже, работает. Хромая часть заключается в том, что вам нужно на самом деле попытаться вызвать метод, чтобы узнать, существует ли он, что в случае регистрации для уведомлений является проблемой, поскольку вы пытаетесь выяснить, существует ли этот метод, прежде чем приступить к созданию UIUserNotificationSettings объект. Кажется, что вызов этого метода с nil, хотя все в порядке, поэтому решение, которое, кажется, работает для меня:
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)
}
После долгих поисков, связанных с этим, ключевая информация пришла из этого выступления на WWDC https://developer.apple.com/videos/wwdc/2014/#407 прямо посередине в разделе «Необязательные методы в протоколах».
В бета-версии Xcode 6.1 вышеуказанный код больше не работает, код ниже работает:
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)
}