web-dev-qa-db-fra.com

Quel est l'équivalent du préprocesseur Swift avec la comparaison de vérification de version iOS?

Je reçois

yld: Symbol not found: _OBJC_CLASS_$_UIUserNotificationSettings

et voici la fonction qui cause l'erreur lorsque l'application s'exécute sur un périphérique iOS7 et sans même appeler la fonction 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 du tout que cette méthode soit accessible lors de l'exécution sur un périphérique iOS7. Je ne veux pas de chèque de sélection à l'intérieur car cela signifie que la méthode est disponible pour commencer.

Ce que je veux, c'est un paramètre de configuration de construction permettant de vérifier la version: je ne trouve pas le moyen d'écrire une macro de préprocesseur équivalente à Swift pour rechercher la version iOS appropriée et de 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 suggère des fonctions et des génériques pour remplacer des macros complexes, mais dans ce cas, j'ai besoin d'un contrôle de précompilation de la configuration de construction pour éviter le traitement de fonctions non déclarées. Aucune suggestion.

17
Essa A. Haddad

Les autres réponses ne mentionnent pas les moyens appropriés de vérifier la version du système. Vous ne devez absolument jamais utiliser: Device.systemVersion Vous ne devez pas créer de macros personnalisées pour vérifier les numéros de version, et vous ne devez pas creuser au-delà des bibliothèques définies spécifiquement par Apple pour cette tâche.

Il y a un excellent article détaillant ceci ici .

Notez que Swift 2.0 vous permet de vérifier directement si un numéro de version de système d'exploitation 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 du système.

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

Notez que si vous avez besoin de fonctionnalités similaires à une 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 attributs dans Swift, vous pouvez vous référer à documentation Apple .

14
TheCodingArt

Dans 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

Puis dans d'autres fichiers

if iOS8
{

}
else
{

}
12
ChikabuZ

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


Voici une solution de contournement (peut-être pas si excellente): associez explicitement le lien UIKit à un état faible (je sais que les déclarations import sont supposées renvoyer déjà à des frameworks, mais nous le faisons explicitement quand même).

  • Cliquez sur le projet dans Xcode
  • sélectionnez la cible dans le menu déroulant en haut à gauche
  • aller à l'onglet général
  • faites défiler jusqu'à Cadres et bibliothèques liés
  • ajouter UIKit.framework
  • changer le statut de obligatoire à facultatif

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

En Objective-C, même avec Obligatoire, le compilateur a automatiquement lié les symboles dont la disponibilité était supérieure à la cible de déploiement, et a laissé les autres fortement liés. Je ne sais pas pourquoi cela ne fonctionne pas avec Swift.

4
user102008

var systemVersion = UIDevice.currentDevice (). systemVersion

4
Venu Gopal Tewari

Selon Apple, il n'y a pas d'appels de préprocesseur dans Swift, mais le code Swift peut être compilé sous condition en fonction de l'évaluation des configurations de construction dans deux fonctions. Pour l'instant, nous avons os() pour un choix d'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 une bonne idée pour les versions ultérieures de Swift).

2
GlennRay

Vous pouvez vérifier la version iOS par -

let iosVersion = UIDevice.currentDevice().systemVersion

Et comparez-le avec 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
}

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ésoudra votre question.

1
cheeseRoot