Подтвердить что ты не робот

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

4b9b3361

Ответ 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