Ответ 1
Подробный пост от одного и только матового: http://nshipster.com/swift-system-version-checking/
Я получаю
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 предлагает функции и обобщения для замены сложных макросов, но в этом случае мне нужна предварительная компиляция конфигурации конфигурации, чтобы избежать обработки необъявленных функций. Любые предложения.
Подробный пост от одного и только матового: http://nshipster.com/swift-system-version-checking/
В других ответах не упоминаются правильные способы проверки версии системы. Вы никогда не должны использовать: 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.
В 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
{
}
Обновление: Это исправлено в Xcode 6 beta 6 (сборка 6A280e)
Здесь (возможно, не очень большой) обходной путь: явно ссылается на UIKit слабо (я знаю, что операторы import
должны ссылаться на фреймворки уже, но мы делаем это явно в любом случае).
Это может привести к слабому соединению всех UIKit, что может повлиять на производительность. Не уверен.
В Objective-C, даже с Required, компилятор автоматически сослал символы, чья доступность выше цели развертывания, и оставьте остальные сильно связанными. Я не знаю, почему это не работает с Swift.
var systemVersion = UIDevice.currentDevice(). systemVersion
Согласно Apple, в Swift нет препроцессорных вызовов, но код Swift можно условно скомпилировать на основе оценки конфигураций сборки в двух функциях. Пока мы получаем
os()
для выбора OSX или iOS и arch()
для выбора x86_64, arm, arm64 или i386. Итак, вы можете оценить #if os(iOS)
, но не #if os(iOS8)
(хотя это выглядит как хорошая идея для дальнейших версий Swift).
Вы можете проверить версию 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
}
Вы можете увидеть более подробную информацию здесь. Надеюсь, это решает ваш запрос.
Решение для проверки версии 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, вы, к сожалению, заметите, что никогда не пройдете через оставшуюся часть фрагмент кода.