Как мне сделать слабую связь в Swift?
В Objective-C, если бы я хотел использовать определенный класс, который присутствует только в новой версии iOS, я бы сделал что-то вроде этого:
if( [UIBlurEffect class] ) {
// do something with UIBlurEffect
}
else {
// gracefully fallback to old behavior
}
Тем не менее, эквивалент Swift:
if UIBlurEffect.self != nil {
let blur: UIBlurEffect = UIBlurEffect(...)
// ...
else {
// ...
}
// also occurs with NSClassFromString("UIBlurEffect")
не имеет такой же функциональности.
Если запустить в среде, где NSNewFeature
есть в наличии, все хорошо. Но если класс не определен, я получаю ошибку ссылки при запуске приложения:
dyld: Symbol not found: _OBJC_CLASS_$_UIBlurEffect
Так как же сделать слабое связывание в Swift?
Редактировать Добавлено UIBlurEffect
как конкретный пример.
2 ответа
Похоже, я понял, что вы можете сделать
я использовал
NSClassFromString()
проверить, доступен ли класс на устройстве, т.е.if NSClassFromString("UIBlurEffect") { let blur = UIBlurEffect(...) //... } else { //... }
Нужно сделать
UIKit.framework
(или другой соответствующий каркас) необязательно. Если вы создадите приложение на основе Swift в XCode6-BetaX, все фреймворки не будут явно добавлены на этапе построения ссылки, поэтому вам нужно перейти к настройкам цели, добавитьUIKit.framework
в качестве связанного фреймворка (в разделе "Связать двоичные файлы с библиотеками") и изменить его статус наOptional
, Этот шаг делает свое дело, и мне удалось запустить код конкретной версии без проблем.
Обновление: вам больше не нужно делать его необязательным, поскольку Xcode 6 beta 6 (через @user102008)
Обновление 2: Вы не можете фактически выполнить неявное, если оператор проверяет на ноль (начиная с Xcode 6 Beta 5). Вы должны утверждать это так:
if NSClassFromString("UIBlurEffect") != nil {
let blur = UIBlurEffect(...)
//...
}
else {
//...
}
(через @ Даниель-Галаско)
Просто добавьте мои два цента, так как я в конечном итоге использовал это к моему непосредственному разочарованию при распространении приложения нашим тестерам. В компиляторе Swift есть ошибка (Xcode <= 6.1.1), из-за которой при сборке в режиме Release компилятор фактически не возвращает nil при вызове NSClassFromString
,
Чтобы проверить меня, просто измените вашу конфигурацию на Release и посмотрите, как она падает.
В итоге мне пришлось явно проверять версии iOS или простой вызов responsedsToSelector в другом месте.
Итак, где мой код выглядел так:
if NSClassFromString("UIVisualEffectView") != nil {
//use the blur safely
} else {
//abandon blur! try something safer
}
В итоге мне пришлось использовать это вместо
switch UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch) {
case .OrderedSame, .OrderedDescending:
//go wild with blur
case .OrderedAscending:
//blur shall not pass here!
}
Этот вопрос касался той же проблемы - UIAlertView вылетает приложение на iOS 7