Как мне сделать слабую связь в 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 ответа

Похоже, я понял, что вы можете сделать

  1. я использовал NSClassFromString() проверить, доступен ли класс на устройстве, т.е.

    if NSClassFromString("UIBlurEffect") {
        let blur = UIBlurEffect(...)
        //...
    }
    else {
        //...
    }
    
  2. Нужно сделать 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

Другие вопросы по тегам