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

Что такое препроцессор Swift, эквивалентный сопоставлению проверки версий iOS?

Я получаю

yld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings

и здесь функция, вызывающая ошибку , когда приложение запущено на устройстве iOS7 и даже не вызывает функцию вообще в коде.

func reigsterForRemoteUserNotifications(notificationTypes: UIUserNotificationType, categories: NSSet) {
        let userNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: categories)
        (UIApplication.sharedApplication()).registerUserNotificationSettings(userNotificationSettings)
        UIApplication.sharedApplication().registerForRemoteNotifications()
    }

Я не хочу, чтобы этот метод был доступен вообще при запуске на устройстве iOS7. Я не хочу, чтобы внутри него была выбрана проверка, потому что это означает, что метод можно использовать для начала.

То, что я хочу, это параметр конфигурации сборки для проверки версии:  Я не могу найти способ написать быстрый эквивалентный макрос препроцессора для проверки правильной версии iOS и пренебрегать новыми и незаявленными функциями библиотеки iOS 8.

#if giOS8OrGreater
// declare the functions that are iOS 8 specific
#else 
// declare the functions that are iOS 7 specific

#endif

В документации apple предлагает функции и обобщения для замены сложных макросов, но в этом случае мне нужна предварительная компиляция конфигурации конфигурации, чтобы избежать обработки необъявленных функций. Любые предложения.

4b9b3361

Ответ 2

В других ответах не упоминаются правильные способы проверки версии системы. Вы никогда не должны использовать: Device.systemVersion Вы не должны настраивать пользовательские макросы для проверки номеров версий, и вы не должны копаться за пределами библиотек, которые Apple специально определила для этой задачи.

Там большая статья подробно на это здесь.

Обратите внимание: Swift 2.0 позволяет вам напрямую проверить, доступен ли номер версии ОС через:

if #available(iOS 10.0, *) {
    // modern code
} else {
    // Fallback on earlier versions
}

До Swift 2.0 рекомендованный подход выполнялся с помощью системных макросов:

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_0) {
    // do stuff for iOS 9 and newer
} else {
    // do stuff for older versions than iOS 9
}

или через:

    if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) {
    // modern code
}

За все, что не хватает за системными макросами.

Любой другой подход был преуменьшен как ненадежный и не рекомендованный Apple. На самом деле есть подход, который сломается в iOS 10.

Обратите внимание: если вам нужна макрокоманда, как функция, и вы хотите использовать # #available вы можете использовать @available определенные в этой статье следующим образом:

 @available(iOS 7, *)
func iOS7Work() {
    // do stuff

    if #available(iOS 8, *) {
        iOS8Work()
    }
}

@available(iOS 8, *)
func iOS8Work() {
    // do stuff
    if #available(iOS 9, *) {
        iOS9Work()
    }
}

@available(iOS 9, *)
func iOS9Work() {
    // do stuff
}

Для получения дополнительной информации об атрибутах в Swift вы можете обратиться к документации Apple.

Ответ 3

В Constants.swift:

Swift 1:

let Device = UIDevice.currentDevice()
private let iosVersion = NSString(string: Device.systemVersion).doubleValue

Swift 2:

let Device = UIDevice.currentDevice()
private let iosVersion = Double(Device.systemVersion) ?? 0 

let iOS8 = iosVersion >= 8
let iOS7 = iosVersion >= 7 && iosVersion < 8

Затем в других файлах

if iOS8
{

}
else
{

}

Ответ 4

Обновление: Это исправлено в Xcode 6 beta 6 (сборка 6A280e)


Здесь (возможно, не очень большой) обходной путь: явно ссылается на UIKit слабо (я знаю, что операторы import должны ссылаться на фреймворки уже, но мы делаем это явно в любом случае).

  • Нажмите на проект в Xcode
  • выберите цель в раскрывающемся списке вверху слева.
  • перейдите на вкладку Общие
  • прокрутите вниз до Linked Frameworks и Libraries.
  • добавить UIKit.framework
  • изменить статус от обязательного к необязательному

Это может привести к слабому соединению всех UIKit, что может повлиять на производительность. Не уверен.

В Objective-C, даже с Required, компилятор автоматически сослал символы, чья доступность выше цели развертывания, и оставьте остальные сильно связанными. Я не знаю, почему это не работает с Swift.

Ответ 5

var systemVersion = UIDevice.currentDevice(). systemVersion

Ответ 6

Согласно Apple, в Swift нет препроцессорных вызовов, но код Swift можно условно скомпилировать на основе оценки конфигураций сборки в двух функциях. Пока мы получаем os() для выбора OSX или iOS и arch() для выбора x86_64, arm, arm64 или i386. Итак, вы можете оценить #if os(iOS), но не #if os(iOS8) (хотя это выглядит как хорошая идея для дальнейших версий Swift).

Ответ 7

Вы можете проверить версию iOS на -

let iosVersion = UIDevice.currentDevice().systemVersion

И сравните его, используя NSStringCompareOptions.NumericSearch

switch iosVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)
{
    case .OrderedSame, .OrderedDescending:
        //iOS>=8.0.0
        return LAContext()
    case .OrderedAscending:
        //iOS<8.0.0
        return nil
}

Вы также можете использовать новые API NSProcessInfo, но они недоступны для iOS 7.

if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 8, minorVersion: 0, patchVersion: 0)) {
//iOS>=8.0.0
}

Вы можете увидеть более подробную информацию здесь. Надеюсь, это решает ваш запрос.

Ответ 8

Решение для проверки версии iOS в Swift

switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSStringCompareOptions.NumericSearch)) {
    case .OrderedAscending:
       println("iOS < 8.0")

    case .OrderedSame, .OrderedDescending:
       println("iOS >= 8.0")
}

Con этого решения: просто неправильно проверять номера версий ОС, в зависимости от того, как вы это делаете. Поэтому никогда не следует жестко привязывать кодовые зависимости, всегда проверяйте возможности, возможности или существование класса. Учти это; Apple может выпускать обратно совместимую версию класса, если они это сделали, то код, который вы предлагаете, никогда не будет использовать его, поскольку ваша логика ищет номер версии ОС и НЕ существование класса.

(Источник этой информации)

Решение для проверки существования класса в Swift

if (objc_getClass("UIAlertController") == nil) {
   // iOS 7
} else {
   // iOS 8+
}

Не используйте if (NSClassFromString("UIAlertController") == nil), потому что он корректно работает на iOS-симуляторе с использованием iOS 7.1 и 8.2, но если вы протестируете на реальном устройстве с помощью iOS 7.1, вы, к сожалению, заметите, что никогда не пройдете через оставшуюся часть фрагмент кода.