Quel est le préprocesseur Swift équivalent à la comparaison de vérification de version iOS?

Je reçois

yld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings 

et voici la fonction qui provoque l'erreur lorsque l'application est en cours d'exécution sur un périphérique iOS7 et sans même appeler la fonction du tout dans le code.

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

Je ne veux pas que cette méthode soit accessible du tout lors de l'exécution sur un périphérique iOS7. Je ne veux pas de vérification sélective à l'intérieur car cela signifie que la méthode est disponible pour commencer.

Ce que je veux est un paramètre de configuration de construction pour vérifier la version: Je ne peux pas find un moyen d'écrire une macro préprocesseur équivalent rapide pour vérifier la bonne version iOS et négliger les nouvelles fonctions de bibliothèque iOS 8 non déclarées.

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

Dans la documentation Apple propose des fonctions et des generics pour replace les macros complexes, mais dans ce cas, j'ai besoin d'une vérification de compilation précomstack pour éviter de traiter des fonctions non déclarées. Aucune suggestion.

Dans Constants.swift :

Swift 1:

 let Device = UIDevice.currentDevice() private let iosVersion = NSSsortingng(ssortingng: 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 

Puis dans d'autres files

 if iOS8 { } else { } 

Toutes les réponses postées ici sont horribles et ignorent toujours la façon de vérifier la version du système. Vous ne devriez absolument jamais utiliser: Device.systemVersion Vous ne devriez pas faire de macros personnalisées pour vérifier les numéros de version, et vous ne devriez pas creuser au-delà des bibliothèques qu'Apple a spécifiquement définies pour cette tâche.

Il y a un bon article détaillant cela ici .

Notez que Swift 2.0 vous permet de vérifier directement si un numéro de version d'OS est disponible via:

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

Avant Swift 2.0, l'approche recommandée était via les macros système fournies:

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

ou via:

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

Pour tout ce qui manque au-delà des macros système.

Toute autre approche a été minimisée comme non fiable et non recommandé par Apple. Il y a en fait une approche qui va casser dans iOS 10.

Notez que si vous avez besoin d'une fonctionnalité de type macro dans une vérification et que vous souhaitez utiliser #available vous pouvez utiliser @available défini dans cet article en tant que tel:

  @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 } 

Pour plus d'informations sur les attributes dans Swift, vous pouvez consulter la documentation d'Apple .

var systemVersion = UIDevice.currentDevice (). systemVersion

Mise à jour: Ceci est corrigé dans Xcode 6 beta 6 (build 6A280e)


Voici une solution de contournement (peut-être less bonne): lier explicitement à UIKit (je sais que import instructions d' import sont déjà liées à des frameworks, mais nous le faisons explicitement de toute façon).

  • Cliquez sur le projet dans Xcode
  • select la cible dans la list déroulante en haut à gauche
  • aller à l'onglet Général
  • faites défiler vers les frameworks et bibliothèques liés
  • append UIKit.framework
  • changer le statut de Obligatoire à Facultatif

Cela peut entraîner une faible binding entre tous les UIKit, ce qui peut affecter les performances. Pas certain.

En Objective-C, même avec Required, le compilateur lia automatiquement les symboles dont la disponibilité est supérieure à la cible de deployment, et laisse les autres fortement liés. Je ne sais pas pourquoi cela ne fonctionne pas avec Swift.

Selon Apple, il n'y a pas d'appel de préprocesseur dans Swift, mais le code Swift peut être compilé conditionnellement en fonction de l'évaluation des configurations de construction dans deux fonctions. Pour l'instant, nous avons os() pour OSX ou iOS et arch() pour un choix de x86_64, arm, arm64 ou i386. Donc, vous pouvez évaluer #if os(iOS) , mais pas #if os(iOS8) (bien que cela semble être une bonne idée pour les autres versions de Swift).

Vous pouvez vérifier la version iOS par –

 let iosVersion = UIDevice.currentDevice().systemVersion 

Et comparez-le en utilisant NSSsortingngCompareOptions.NumericSearch

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

Vous pouvez également utiliser les nouvelles API NSProcessInfo, mais elles ne sont pas disponibles pour iOS 7.

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

Vous pouvez voir plus de détails ici . J'espère que cela résout votre requête.

Un post détaillé par le seul et unique: http://nshipster.com/swift-system-version-checking/

Solution pour vérifier la version iOS dans Swift

 switch (UIDevice.currentDevice().systemVersion.compare("8.0.0", options: NSSsortingngCompareOptions.NumericSearch)) { case .OrderedAscending: println("iOS < 8.0") case .OrderedSame, .OrderedDescending: println("iOS >= 8.0") } 

Con de cette solution: il est simplement une mauvaise pratique de vérifier les numéros de version du operating system, de quelque manière que vous le fassiez. On ne devrait jamais coder les dependencies de cette façon, toujours vérifier les caractéristiques, les capacités ou l'existence d'une class. Considère ceci; Apple peut publier une version rétrocompatible d'une class, si c'est le cas, le code que vous proposez ne l'utilisera jamais car votre logique search un numéro de version de operating system et NON l'existence de la class.

( Source de cette information )

Solution pour vérifier l'existence de la class dans Swift

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

N'utilisez pas if (NSClassFromSsortingng("UIAlertController") == nil) car il fonctionne correctement sur le simulateur iOS en utilisant iOS 7.1 et 8.2, mais si vous testez sur un vrai périphérique en utilisant iOS 7.1, vous remarquerez malheureusement que vous ne passerez jamais à travers la partie else de l'extrait de code.