Как сделать слабую связь в 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
в качестве конкретного примера.
Ответы
Ответ 1
Похоже, я выяснил, что вы можете сделать
-
Я использовал NSClassFromString()
, чтобы проверить, доступен ли класс на устройстве, т.е.
if NSClassFromString("UIBlurEffect") {
let blur = UIBlurEffect(...)
//...
}
else {
//...
}
-
Необходимо сделать необязательным UIKit.framework
(или другую соответствующую структуру). Если вы создаете приложение на основе Swift в XCode6-BetaX, все фреймворки не будут явно добавлены в фазу сборки ссылок, поэтому вам нужно перейти к целевым настройкам, добавьте UIKit.framework
в качестве связанной структуры (в разделе "Link Binary With Раздел" Библиотеки") и изменить его статус на Optional
. Этот шаг делает трюк, и мне удалось запустить конкретный код версии без проблем.
Обновить: вам больше не нужно делать его необязательным, так как Xcode 6 beta 6 (через @user102008)
Обновление 2. Фактически вы не можете выполнять неявные проверки операторов для nil (начиная с Xcode 6 Beta 5). Вам нужно сказать следующее:
if NSClassFromString("UIBlurEffect") != nil {
let blur = UIBlurEffect(...)
//...
}
else {
//...
}
(через @daniel-galasko)
Ответ 2
Просто чтобы добавить мои два цента, так как я в конечном итоге использовал это для моего непосредственного беспокойства при распространении приложения для наших тестировщиков. В компиляторе Swift имеется ошибка (Xcode <= 6.1.1), при которой при создании в режиме Release компилятор фактически не возвращает nil при вызове NSClassFromString
.
Чтобы проверить меня, просто измените конфигурацию на Release и посмотрите, как она сработает.
Мне пришлось явно проверять версии iOS или простой вызов replySoSelector в другом месте.
Итак, где мой код выглядит так:
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