web-dev-qa-db-fra.com

Quel est Swift équivalent de "#ifdef __IPHONE_11_0" d'Objective-C?

Je souhaite utiliser Xcode 9 pour ajouter du code iOS 11 à mon projet tout en conservant la possibilité de compiler le projet avec Xcode 8 qui ne prend en charge que iOS 10.

Dans Objective-C, je peux le faire en utilisant une directive de préprocesseur pour vérifier si __IPHONE_11_0 Est défini. Ce qui masquera le code si je compile avec un SDK de base antérieur à iOS 11. Comme ceci:

#ifdef __IPHONE_11_0
    if (@available(iOS 11.0, *)) {
        self.navigationController.navigationBar.prefersLargeTitles = YES;
    }
#endif

Y a-t-il un moyen de le faire dans Swift?

if #available(iOS 11.0, *) ne fonctionne pas car il s'agit d'une vérification d'exécution.

18
Matthias Bauch

Le SDK iOS 11 est livré avec Swift 3.2 (ou Swift 4), vous pouvez donc utiliser un Swift version check to to accomplir la même chose:

#if Swift(>=3.2)
    if #available(iOS 11.0, *) {
        …
    }
#endif
16
Lily Ballard

Voici la solution proposée par Apple:

if #available(iOS 11.0, *) {
    // iOS 11 specific stuff here
} else {
    // non iOS 11 stuff here
}

Veuillez vous référer à cette ressource (regardez la vidéo à la marque 6:50 pour plus de détails)

4
pesch

Si vous souhaitez mettre la condition en dehors de la fonction, vous pouvez le faire comme ci-dessous.

@available(iOS 11.0, *)
func functionName() {
 // function contents
}
1
Carly

Je comprends. J'ai un vieux Mac que j'aime utiliser qui est trop vieux pour Xcode 9, donc je veux aussi pouvoir parfois compiler mes projets sous Xcode 8.

Mais si tout ce que vous voulez est de prendre en charge à la fois iOS 10 et iOS 11, le moyen le plus simple est de simplement définir le SDK minimum de la cible Xcode sur 10.0 et de toujours compiler avec le SDK iOS 11. Swift fonctionnera pour vous dans ce cas, et vous donnera des erreurs de syntaxe à moins que vous n'utilisiez correctement si #available (iOS 11.0, *) {

Vous pourrez toujours tester sous iOS 10 et iOS 11 et vous n'aurez pas à vous soucier de Xcode 8.

Du point de vue de Xcode 8, vous essayez de compiler le code source du futur. Il n'y a pas de bonne solution pour Xcode 8.

Pour l'avenir, voici la solution:

Dans Xcode 9.3 (Swift 4.1), vous pouvez dire:

#if canImport(MagiciOS12Kit)
  if #available(iOS 12.0, *) {
     MagiciOS12Class.standard.method()
  }
#endif

et votre code sera toujours compilé sous Xcode 9.3, mais en ignorant ce futur truc qui a besoin d'un hypothétique Xcode 10.0 ou version ultérieure.

# si canImport (moduleName) a été ajouté uniquement dans Swift 4.1, que Xcode 8 ne peut pas gérer. Mais même cela ne fonctionne que pour des modules entiers qui Apple s'ajoute à l'avenir. Si Apple étend simplement une classe existante avec de nouvelles méthodes, comme dans votre navigationController.navigationBar.prefersLargeTitles vous avez toujours gagné ' t être en mesure de tester prefersLargeTitles directement, mais vous pouvez trouver un autre framework qui Apple introduit en même temps que prefersLargeTitles et vérifier l'existence de ce cadre avec # if canImport (…).

0
DavidPhillipOster

Vous pouvez y parvenir en faisant cela pour une fonction comme ci-dessous

@available(iOS 11.0, *)
func myFunction() {
 // function defination 
}

Ou si vous voulez vérifier la fonction à l'intérieur, écrivez ceci

if #available(iOS 11.0, *) {
    // iOS 11 specific stuff here
} else if #available(iOS 10.0, *) {
   // iOS 10 specific stuff here
} else {
    // non iOS 11 & 10 stuff here
}
0
Prabhat Pandey