Comment vérifier la version iOS?

848

Je veux vérifier si la iOSversion de l'appareil est supérieure à 3.1.3 ce que j'ai essayé des choses comme:

[[UIDevice currentDevice].systemVersion floatValue]

mais ça ne marche pas, je veux juste un:

if (version > 3.1.3) { }

Comment puis-je atteindre cet objectif?

John
la source
5
Note du modérateur : Au fil du temps, cette question a généré plus de 30 réponses. Avant d'ajouter une nouvelle réponse, assurez - vous que votre solution n'a pas déjà été fournie.
Matt
3
Démarrage de Xcode 7, if #available(iOS 9, *) {}dans Swift. Démarrage de Xcode 9, if (@available(iOS 11, *)) {}dans objective-c.
Cœur

Réponses:

1002

La réponse rapide…


Depuis Swift 2.0, vous pouvez utiliser #availabledans un ifou guardpour protéger du code qui ne doit être exécuté que sur certains systèmes.

if #available(iOS 9, *) {}


Dans Objective-C, vous devez vérifier la version du système et effectuer une comparaison.

[[NSProcessInfo processInfo] operatingSystemVersion] dans iOS 8 et supérieur.

Depuis Xcode 9:

if (@available(iOS 9, *)) {}


La réponse complète…

Dans Objective-C et Swift dans de rares cas, il est préférable d'éviter de se fier à la version du système d'exploitation comme indication des capacités de l'appareil ou du système d'exploitation. Il existe généralement une méthode plus fiable pour vérifier si une fonction ou une classe particulière est disponible.

Vérification de la présence d'API:

Par exemple, vous pouvez vérifier s'il UIPopoverControllerest disponible sur l'appareil actuel en utilisant NSClassFromString:

if (NSClassFromString(@"UIPopoverController")) {
    // Do something
}

Pour les classes faiblement liées, il est sûr d'envoyer un message directement à la classe. En particulier, cela fonctionne pour les frameworks qui ne sont pas explicitement liés comme «requis». Pour les classes manquantes, l'expression est évaluée à nil, à défaut de la condition:

if ([LAContext class]) {
    // Do something
}

Certaines classes, comme CLLocationManageret UIDevice, fournissent des méthodes pour vérifier les capacités des périphériques:

if ([CLLocationManager headingAvailable]) {
    // Do something
}

Vérification de la présence de symboles:

Très occasionnellement, vous devez vérifier la présence d'une constante. Cela est apparu dans iOS 8 avec l'introduction de UIApplicationOpenSettingsURLString, utilisé pour charger l'application Paramètres via -openURL:. La valeur n'existait pas avant iOS 8. Le passage de zéro à cette API se bloquera, vous devez donc prendre soin de vérifier d'abord l'existence de la constante:

if (&UIApplicationOpenSettingsURLString != NULL) {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}

Comparé à la version du système d'exploitation:

Supposons que vous soyez confronté au besoin relativement rare de vérifier la version du système d'exploitation. Pour les projets ciblant iOS 8 et NSProcessInfoversions ultérieures , inclut une méthode pour effectuer des comparaisons de versions avec moins de risques d'erreur:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Les projets ciblant les systèmes plus anciens peuvent utiliser systemVersionsur UIDevice. Apple l'utilise dans leur exemple de code GLSprite .

// A system version of 3.1 or greater is required to use CADisplayLink. The NSTimer
// class is used as fallback when it isn't available.
NSString *reqSysVer = @"3.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) {
    displayLinkSupported = TRUE;
}

Si, pour une raison quelconque, vous décidez que systemVersionc'est ce que vous voulez, assurez-vous de le traiter comme une chaîne ou vous risquez de tronquer le numéro de révision du correctif (par exemple, 3.1.2 -> 3.1).

Justin
la source
161
Il existe des cas spécifiques où la vérification de la version du système est justifiée. Par exemple, quelques classes et méthodes qui étaient privées n 3.x ont été rendues publiques dans 4.0, donc si vous vérifiiez simplement leur disponibilité, vous obtiendriez un résultat erroné dans 3.x. De plus, la façon dont UIScrollViews gère les échelles de zoom a changé subtilement dans 3.2 et au-dessus, vous devrez donc vérifier les versions du système d'exploitation afin de traiter les résultats de manière appropriée.
Brad Larson
2
iOS 3.2 ne semble pas envoyer -viewWillAppearun UISplitViewController. Mon hack est de déterminer si <iOS 4.0 et de l'envoyer moi-même au contrôleur de vue détaillée dans la vue racine -didSelectRowAtIndexPath.
2011 à 9h36
10
Vous devez être un peu prudent ici, car les [@"10.0" compare:@"10" options:NSNumericSearch]retours NSOrderedDescending, qui pourraient bien ne pas être destinés du tout. (Je pourrais m'attendre NSOrderedSame.) C'est au moins une possibilité théorique.
SK9
Oui, je viens de rencontrer un cas où un bogue iOS 5 devait être contourné. respondsToSelectoret al ne feraient pas le travail - doivent comparer les versions.
Hot Licks
2
Avec l'introduction de TVos, cela est même devenu plus important. Voir que TVos renverra 9.0 tandis que le SDK 9.1 est utilisé. Vérifiez donc que la classe ou la méthode (sélecteur) est le meilleur moyen, après cela, vous devez vérifier le NSFoundationVersionNumberet uniquement si cela n'est pas possible, vous devez vérifier les versions du système UIDevice.
rckoenes
1055
/*
 *  System Versioning Preprocessor Macros
 */ 

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

/*
 *  Usage
 */ 

if (SYSTEM_VERSION_LESS_THAN(@"4.0")) {
    ...
}

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"3.1.1")) {
    ...
}
yasirmturk
la source
20
+1. Garder cela dans un en-tête que vous pouvez inclure si nécessaire est la solution la plus simple à laquelle je peux penser. Dans plusieurs cas, cela est plus fiable que de vérifier la disponibilité à l'aide de NSClassFromString. Un autre exemple est dans iAd, où si vous utilisez ADBannerContentSizeIdentifierPortrait dans une version antérieure à 4.2, vous obtiendrez EXEC_BAD_ACCESS, mais l'équivalent ADBannerContentSizeIdentifier320x50 est obsolète après 4.1.
Rab
1
Un autre endroit que j'utilise c'est avec UIPageViewController et en définissant le style sur UIPageViewControllerTransitionStyleScroll dans iOS6.
Paul de Lange
7
Cela ne fonctionne pas pendant 10 secondes. Par exemple, comparer 4.10 et 4.9 donnerait le mauvais résultat.
pzulw
7
Il faut être très prudent lors de l'utilisation de .0numéros facultatifs . Par exemple, SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0.0")donne un résultat incorrect sur iOS 7.0.
Yan, du
1
Je viens de tester de mettre cela dans mon fichier .pch et cela fonctionne très bien (construire avec Xcode 5 au moins)
whyoz
253

Comme suggéré par les documents officiels d'Apple : vous pouvez utiliser le NSFoundationVersionNumber, à partir du NSObjCRuntime.hfichier d'en-tête.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}
CarlJ
la source
40
+1 Il s'agit en fait de l' option la plus sûre et la plus précise ici.
mxcl
8
Um .. NSFoundationVersionNumber_iOS_6_1n'existe pas dans le SDK iOS 5.
Kjuly
2
@Kjuly, vous pouvez définir les numéros de version manquants par vous-même: github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h (jetez un œil à la ligne 102-130)
CarlJ
3
non, vous vous trompez, NSFoundationVersionNumber_iOS_7_0 n'existe pas. Mais bon, on pourrait le définir avec #ifndef NSFoundationVersionNumber_iOS_7_0 #define NSFoundationVersionNumber_iOS_7_0 1047.00 #endif. Pour éviter de gâcher comme ça, je suis allé avec la macro SYSTEM_VERSION_LESS_THAN (v) de yasirmturk
Cœur
7
Non, mais Apple ajoutera le NSFoundationVersionNumber_iOS_8_0dans iOS 9. il suffit de vérifier NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
CarlJ
111

Démarrage de Xcode 9, dans Objective-C :

if (@available(iOS 11, *)) {
    // iOS 11 (or newer) ObjC code
} else {
    // iOS 10 or older code
}

Démarrage de Xcode 7, dans Swift :

if #available(iOS 11, *) {
    // iOS 11 (or newer) Swift code
} else {
    // iOS 10 or older code
}

Pour la version, vous pouvez spécifier le MAJOR, le MINOR ou le PATCH (voir http://semver.org/ pour les définitions). Exemples:

  • iOS 11et iOS 11.0sont la même version minimale
  • iOS 10, iOS 10.3, iOS 10.3.1Sont différentes versions minimales

Vous pouvez saisir des valeurs pour n'importe lequel de ces systèmes:

  • iOS, macOS, watchOS,tvOS

Exemple de cas réel tiré de l' un de mes pods :

if #available(iOS 10.0, tvOS 10.0, *) {
    // iOS 10+ and tvOS 10+ Swift code
} else {
    // iOS 9 and tvOS 9 older code
}

Documentation

Cœur
la source
Comment cela peut-il être inversé dans Objective-C ou Swift?
Legoless
@Legolessif (...) {} else { ... }
Cœur
Puis-je utiliser guarddans Objective-C au lieu de laisser le bloc ouvert et le retrait dans l' elseinstruction?
Legoless
@Legoless non, utilisez simplement un ifbloc vide suivi d'un else.
Cœur
1
C'est la solution que j'ai actuellement, je voulais juste éviter une indentation inutile et des ifblocs vides .
Legoless
45

Ceci est utilisé pour vérifier la version compatible du SDK dans Xcode, c'est si vous avez une grande équipe avec différentes versions de Xcode ou plusieurs projets prenant en charge différents SDK qui partagent le même code:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
  //programming in iOS 8+ SDK here
#else
  //programming in lower than iOS 8 here   
#endif

Ce que vous voulez vraiment, c'est vérifier la version iOS sur l'appareil. Vous pouvez le faire avec ceci:

if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
  //older than iOS 8 code here
} else {
  //iOS 8 specific code here
}

Version Swift:

if let version = Float(UIDevice.current.systemVersion), version < 9.3 {
    //add lower than 9.3 code here
} else {
    //add 9.3 and above code here
}

Les versions actuelles de swift devraient utiliser ceci:

if #available(iOS 12, *) {
    //iOS 12 specific code here
} else {
    //older than iOS 12 code here
}
Travis M.
la source
37

Essayer:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 3.1.3
} else {
    // OS version < 3.1.3
}
Jonathan Grynspan
la source
2
Pourquoi ne pas inverser l'ordre ici et enregistrer une comparaison, car @ "3.1.3" et systemVersion sont des NSStrings? C'est-à-dire: `if ([@" 3.1.3 "compare: [UIDevice currentDevice] .systemVersion options: NSNumericSearch] == NSOrderedDescending); // OS version> = 3.1.3 else; // OS version <3.1.3`
Rob
3
Faire cela peut rendre la logique moins claire. L'opération doit cependant être équivalente.
Jonathan Grynspan,
1
Une comparaison entre deux entiers n'est sûrement pas très chère.
KPM
C'est vraiment une question de style. Le surcoût de l'envoi des messages l'emportera largement sur la comparaison d'entiers supplémentaires.
Jonathan Grynspan
35

Approche préférée

Dans Swift 2.0, Apple a ajouté la vérification de la disponibilité en utilisant une syntaxe beaucoup plus pratique (en savoir plus ici ). Vous pouvez maintenant vérifier la version du système d'exploitation avec une syntaxe plus propre:

if #available(iOS 9, *) {
    // Then we are on iOS 9
} else {
    // iOS 8 or earlier
}

Ceci est préférable à la vérification, respondsToSelectoretc. ( Quoi de neuf dans Swift ). Maintenant, le compilateur vous avertira toujours si vous ne protégez pas correctement votre code.


Pre Swift 2.0

La nouveauté d'iOS 8 NSProcessInfopermet de meilleurs contrôles de version sémantique.

Déploiement sur iOS 8 et supérieur

Pour les cibles de déploiement minimales d' iOS 8.0 ou supérieur, utilisez NSProcessInfo operatingSystemVersionou isOperatingSystemAtLeastVersion.

Cela donnerait les résultats suivants:

let minimumVersion = NSOperatingSystemVersion(majorVersion: 8, minorVersion: 1, patchVersion: 2)
if NSProcessInfo().isOperatingSystemAtLeastVersion(minimumVersion) {
    //current version is >= (8.1.2)
} else {
    //current version is < (8.1.2)
}

Déploiement sur iOS 7

Pour les cibles de déploiement minimum d' iOS 7.1 ou ci - dessous, utilisez comparer avec NSStringCompareOptions.NumericSearchle UIDevice systemVersion.

Cela donnerait:

let minimumVersionString = "3.1.3"
let versionComparison = UIDevice.currentDevice().systemVersion.compare(minimumVersionString, options: .NumericSearch)
switch versionComparison {
    case .OrderedSame, .OrderedDescending:
        //current version is >= (3.1.3)
        break
    case .OrderedAscending:
        //current version is < (3.1.3)
        fallthrough
    default:
        break;
}

Plus de lecture sur NSHipster .

Daniel Galasko
la source
9

Je garde toujours ceux-ci dans mon fichier Constants.h:

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES) 
#define IS_OS_5_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0)
#define IS_OS_6_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
#define IS_OS_7_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
#define IS_OS_8_OR_LATER    ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
Segev
la source
Génial. Mieux vaut placer ceci dans le .pchfichier de votre projet XCode
Vaibhav Jhaveri
1
Je place toutes mes constantes dans mon Constants.hfichier qui est importé dans mon pchfichier.
Segev
6
+(BOOL)doesSystemVersionMeetRequirement:(NSString *)minRequirement{

// eg  NSString *reqSysVer = @"4.0";


  NSString *currSysVer = [[UIDevice currentDevice] systemVersion];

  if ([currSysVer compare:minRequirement options:NSNumericSearch] != NSOrderedAscending)
  {
    return YES;
  }else{
    return NO;
  }


}
Jef
la source
Les périodes @Jef ne sont pas des décimales dans le contrôle de version et sont pertinentes. Votre réponse n'ignore pas les périodes, elle échouerait si c'était le cas. Lors du contrôle de version, chaque élément séparé par des points est un nombre complet. Ex: «1.23.45» est supérieur à «1.2.345» car le deuxième élément «23» est supérieur à «2». Si vous éliminiez les périodes, ce serait le même nombre.
Andres Canella
6

Avec la classe Version qui est contenue dans le projet nv-ios-version (licence Apache, version 2.0), il est facile d'obtenir et de comparer la version iOS. Un exemple de code ci-dessous vide la version iOS et vérifie si la version est supérieure ou égale à 6.0.

// Get the system version of iOS at runtime.
NSString *versionString = [[UIDevice currentDevice] systemVersion];

// Convert the version string to a Version instance.
Version *version = [Version versionWithString:versionString];

// Dump the major, minor and micro version numbers.
NSLog(@"version = [%d, %d, %d]",
    version.major, version.minor, version.micro);

// Check whether the version is greater than or equal to 6.0.
if ([version isGreaterThanOrEqualToMajor:6 minor:0])
{
    // The iOS version is greater than or equal to 6.0.
}

// Another way to check whether iOS version is
// greater than or equal to 6.0.
if (6 <= version.major)
{
    // The iOS version is greater than or equal to 6.0.
}

Page du projet: nv-ios-version
TakahikoKawasaki / nv-ios-version

Blog: obtenir et comparer la version iOS à l'exécution avec la classe Version
Obtenir et comparer la version iOS à l'exécution avec la classe Version

Takahiko Kawasaki
la source
5

Nouvelle façon de vérifier la version du système à l'aide de swift Forget [[UIDevice currentDevice] systemVersion] et NSFoundationVersionNumber.

Nous pouvons utiliser NSProcessInfo -isOperatingSystemAtLeastVersion

     import Foundation

     let yosemite = NSOperatingSystemVersion(majorVersion: 10, minorVersion: 10, patchVersion: 0)
     NSProcessInfo().isOperatingSystemAtLeastVersion(yosemite) // false
Govind
la source
5

UIDevice + IOSVersion.h

@interface UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion;
+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion

@end

UIDevice + IOSVersion.m

#import "UIDevice+IOSVersion.h"

@implementation UIDevice (IOSVersion)

+ (BOOL)isCurrentIOSVersionEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedSame;
}

+ (BOOL)isCurrentIOSVersionGreaterThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedDescending;
}

+ (BOOL)isCurrentIOSVersionGreaterThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] == NSOrderedAscending;
}

+ (BOOL)isCurrentIOSVersionLessThanOrEqualToVersion:(NSString *)iOSVersion
{
    return [[[UIDevice currentDevice] systemVersion] compare:iOSVersion options:NSNumericSearch] != NSOrderedDescending;
}

@end
Oliver Pearmain
la source
4

En général, il vaut mieux demander si un objet peut exécuter un sélecteur donné, plutôt que de vérifier un numéro de version pour décider s'il doit être présent.

Lorsque ce n'est pas une option, vous devez être un peu prudent ici car des [@"5.0" compare:@"5" options:NSNumericSearch]retours NSOrderedDescendingqui pourraient bien ne pas être du tout destinés; Je pourrais m'attendreNSOrderedSame ici. C'est au moins une préoccupation théorique, qui mérite d'être défendue à mon avis.

Il convient également de considérer la possibilité d'une entrée de mauvaise version qui ne peut pas être raisonnablement comparée. Apple fournit les trois constantes prédéfinies NSOrderedAscending, NSOrderedSameet NSOrderedDescendingmais je ne peux penser à une utilisation pour quelque chose appeléNSOrderedUnordered en cas je ne peux pas comparer deux choses et je veux retourner une valeur indiquant cela.

De plus, il n'est pas impossible qu'Apple élargisse un jour leurs trois constantes prédéfinies pour permettre une variété de valeurs de retour, ce qui rend la comparaison != NSOrderedAscendingimprudente.

Cela dit, considérez le code suivant.

typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;

@interface SKComparator : NSObject
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;
@end

@implementation SKComparator
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {
  if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:@".."].location != NSNotFound ||
    [vTwo rangeOfString:@".."].location != NSNotFound) {
    return SKOrderedNotOrdered;
  }
  NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
  NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];
  NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];
  if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {
    return SKOrderedNotOrdered;
  }
  NSArray *vOneArray = [vOne componentsSeparatedByString:@"."];
  NSArray *vTwoArray = [vTwo componentsSeparatedByString:@"."];
  for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {
    NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];
    NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];
    if (vOneInt > vTwoInt) {
      return kSKOrderedDescending;
    } else if (vOneInt < vTwoInt) {
      return kSKOrderedAscending;
    }
  }
  if ([vOneArray count] > [vTwoArray count]) {
    for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {
      if ([[vOneArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedDescending;
      }
    }
  } else if ([vOneArray count] < [vTwoArray count]) {
    for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {
      if ([[vTwoArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedAscending;
      }
    }
  }
  return kSKOrderedSame;
}
@end
SK9
la source
4
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
        // Your code here
}

Où bien sûr, NSFoundationVersionNumber_iOS_6_1doit être remplacé par par applicable à la version iOS que vous souhaitez vérifier. Ce que j'ai maintenant écrit sera probablement beaucoup utilisé lors du test si un appareil exécute iOS7 ou une version précédente.

OscarWyck
la source
4

un peu tard pour la fête, mais à la lumière d'iOS 8.0, cela pourrait être pertinent:

si vous pouvez éviter d'utiliser

[[UIDevice currentDevice] systemVersion]

Vérifiez plutôt l'existence d'une méthode / classe / quoi que ce soit d'autre.

if ([self.yourClassInstance respondsToSelector:@selector(<yourMethod>)]) 
{ 
    //do stuff 
}

Je l'ai trouvé utile pour le gestionnaire d'emplacement où je dois appeler requestWhenInUseAuthorization pour iOS 8.0 mais la méthode n'est pas disponible pour iOS <8

Denis Kanygin
la source
3
#define _kisiOS7 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)

if (_kisiOS7) {
            NSLog(@"iOS7 or greater")
} 
else {
           NSLog(@"Less than iOS7");
}
Gaurav Gilani
la source
3

Je sais que c'est une vieille question, mais quelqu'un aurait dû mentionner les macros de compilation dans Availability.h. Toutes les autres méthodes ici sont des solutions d'exécution et ne fonctionneront pas dans un fichier d'en-tête, une catégorie de classe ou une définition ivar.

Pour ces situations, utilisez

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0
  // iOS 6+ code here
#else
  // Pre iOS 6 code here
#endif

h / t cette réponse

bcattle
la source
3
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Ajoutez ensuite une condition if comme suit: -

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
   //Your code
}       
Sumit Kumar Saha
la source
2

Il existe des versions comme 7.0 ou 6.0.3, nous pouvons donc simplement convertir la version en chiffres à comparer. si la version est comme 7.0, ajoutez-y simplement un autre ".0" puis prenez sa valeur numérique.

 int version;
 NSString* iosVersion=[[UIDevice currentDevice] systemVersion];
 NSArray* components=[iosVersion componentsSeparatedByString:@"."];
 if ([components count]==2) {
    iosVersion=[NSString stringWithFormat:@"%@.0",iosVersion];

 }
 iosVersion=[iosVersion stringByReplacingOccurrencesOfString:@"." withString:@""];
 version=[iosVersion integerValue];

Pour 6.0.0

  if (version==600) {
    // Do something
  }

pour 7.0

 if (version==700) {
   // Do something
 }
NaXir
la source
la simple suppression des décimales est la mauvaise approche. considérons un composant de plus d'un caractère, par exemple 6.1.10. alors cet algorithme donnera 6110 > 700, ce qui n'est pas correct.
ardnew
Je comprends qu'Apple est mauvais pour déployer de nouvelles versions, mais dans la plupart des cas, le deuxième numéro de la version n'a jamais dépassé 5, donc 10 est hors de question. Il s'agit d'une approche ad hoc, donc si elle gère le boîtier pour 2 composants, vous pouvez la modifier pour gérer quatre boîtiers si vous voulez le faire manuellement. Quoi qu'il en soit, cette approche a été commentée au moment d'iOS6 ou 7. iOS 9 et 10 ont de bien meilleures façons de le vérifier, c'est-à-dire #disponible.
NaXir
2

Essayez le code ci-dessous:

NSString *versionString = [[UIDevice currentDevice] systemVersion];
annu
la source
2

Juste pour récupérer la valeur de la chaîne de version du système d'exploitation:

[[UIDevice currentDevice] systemVersion]
Javier Calatrava Llavería
la source
1

En tant que variante de la solution yasimturks, j'ai défini une fonction et quelques valeurs d'énumération au lieu de cinq macros. Je le trouve plus élégant, mais c'est une question de goût.

Usage:

if (systemVersion(LessThan, @"5.0")) ...

Fichier .h:

typedef enum {
  LessThan,
  LessOrEqual,
  Equal,
  GreaterOrEqual,
  GreaterThan,
  NotEqual
} Comparison;

BOOL systemVersion(Comparison test, NSString* version);

Fichier .m:

BOOL systemVersion(Comparison test, NSString* version) {
  NSComparisonResult result = [[[UIDevice currentDevice] systemVersion] compare: version options: NSNumericSearch];
  switch (test) {
    case LessThan:       return result == NSOrderedAscending;
    case LessOrEqual:    return result != NSOrderedDescending;
    case Equal:          return result == NSOrderedSame;
    case GreaterOrEqual: return result != NSOrderedAscending;
    case GreaterThan:    return result == NSOrderedDescending;
    case NotEqual:       return result != NSOrderedSame;
  }
}

Vous devez ajouter le préfixe de votre application aux noms, en particulier au Comparisontype.

jcsahnwaldt dit GoFundMonica
la source
1

En utilisant la méthode recommandée référencée ... s'il n'y a pas de définition dans les fichiers d'en-tête, vous pouvez toujours obtenir la version imprimée sur la console avec un périphérique de la version IOS souhaitée.

- (BOOL) isIOS8OrAbove{
    float version802 = 1140.109985;
    float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?
    NSLog(@"la version actual es [%f]", NSFoundationVersionNumber);
    if (NSFoundationVersionNumber >= version8){
        return true;
    }
    return false;
}
tyoc213
la source
1

Solution pour vérifier la version iOS dans 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")
}

Inconvénient de cette solution: il est tout simplement mauvais de vérifier les numéros de version du système d'exploitation, quelle que soit la façon dont vous le faites. Il ne faut jamais durer les dépendances de code de cette manière, toujours vérifier les fonctionnalités, les capacités ou l'existence d'une classe. Considère ceci; Apple peut publier une version rétrocompatible d'une classe, si c'est le cas, le code que vous proposez ne l'utilisera jamais car votre logique recherche un numéro de version du système d'exploitation et NON l'existence de la classe.

( Source de cette information )

Solution pour vérifier l'existence de classe dans Swift

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

Ne l'utilisez pas if (NSClassFromString("UIAlertController") == nil)car il fonctionne correctement sur le simulateur iOS utilisant iOS 7.1 et 8.2, mais si vous testez sur un appareil réel utilisant iOS 7.1, vous remarquerez malheureusement que vous ne passerez jamais par le reste de l'extrait de code.

Roi-sorcier
la source
Pourquoi voter contre? Cette solution fonctionne parfaitement avec Swift et toute version iOS. En particulier, la vérification de l'existence de la classe est tout simplement parfaite.
King-Wizard
1
#define IsIOS8 (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1)
Gank
la source
0

Une version plus générique dans Obj-C ++ 11 (vous pourriez probablement remplacer certaines de ces choses par les fonctions NSString / C, mais c'est moins détaillé. Cela vous donne deux mécanismes. SplitSystemVersion vous donne un tableau de toutes les parties qui est utile si vous voulez simplement activer la version principale (par exemple switch([self splitSystemVersion][0]) {case 4: break; case 5: break; }).

#include <boost/lexical_cast.hpp>

- (std::vector<int>) splitSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    std::vector<int> versions;
    auto i = version.begin();

    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        versions.push_back(boost::lexical_cast<int>(versionPart));
    }

    return versions;
}

/** Losslessly parse system version into a number
 * @return <0>: the version as a number,
 * @return <1>: how many numeric parts went into the composed number. e.g.
 * X.Y.Z = 3.  You need this to know how to compare again <0>
 */
- (std::tuple<int, int>) parseSystemVersion {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end()) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    return {versionAsNumber, nParts};
}


/** Assume that the system version will not go beyond X.Y.Z.W format.
 * @return The version string.
 */
- (int) parseSystemVersionAlt {
    std::string version = [[[UIDevice currentDevice] systemVersion] UTF8String];
    int versionAsNumber = 0;
    int nParts = 0;

    auto i = version.begin();
    while (i != version.end() && nParts < 4) {
        auto nextIllegalChar = std::find_if(i, version.end(), [] (char c) -> bool { return !isdigit(c); } );
        std::string versionPart(i, nextIllegalChar);
        i = std::find_if(nextIllegalChar, version.end(), isdigit);

        int part = (boost::lexical_cast<int>(versionPart));
        versionAsNumber = versionAsNumber * 100 + part;
        nParts ++;
    }

    // don't forget to pad as systemVersion may have less parts (i.e. X.Y).
    for (; nParts < 4; nParts++) {
        versionAsNumber *= 100;
    }

    return versionAsNumber;
}
Vitali
la source
0

Essaye ça

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { 
// do some work
}
Muhammad Aamir Ali
la source
Expliquez ce que cela fait.
Kevin Panko
if vérifiera si la version du système d'exploitation est iOS 7 ou non
Muhammad Aamir Ali
0
float deviceOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
float versionToBeCompared = 3.1.3; //(For Example in your case)

if(deviceOSVersion < versionToBeCompared)
   //Do whatever you need to do. Device version is lesser than 3.1.3(in your case)
else 
   //Device version should be either equal to the version you specified or above
GJDK
la source
float versionToBeCompared = 3.1.3;ne peut même pas compiler.
Pang
0

Exemple rapide qui fonctionne réellement:

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

N'utilisez pas NSProcessInfo car il ne fonctionne pas sous 8.0, donc c'est à peu près inutile jusqu'en 2016

Esqarrouth
la source
0

Voici une version rapide:

struct iOSVersion {
    static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue
    static let iOS7 = (Version.SYS_VERSION_FLOAT < 8.0 && Version.SYS_VERSION_FLOAT >= 7.0)
    static let iOS8 = (Version.SYS_VERSION_FLOAT >= 8.0 && Version.SYS_VERSION_FLOAT < 9.0)
    static let iOS9 = (Version.SYS_VERSION_FLOAT >= 9.0 && Version.SYS_VERSION_FLOAT < 10.0)
}

Usage:

if iOSVersion.iOS8 {
    //Do iOS8 code here
}
Swinny89
la source
Je pense que la version devrait être iOSVersion en ligne 3-6 comme struct iOSVersion { static let SYS_VERSION_FLOAT = (UIDevice.currentDevice().systemVersion as NSString).floatValue static let iOS7 = (iOSVersion.SYS_VERSION_FLOAT < 8.0 && iOSVersion.SYS_VERSION_FLOAT >= 7.0) static let iOS8 = (iOSVersion.SYS_VERSION_FLOAT >= 8.0 && iOSVersion.SYS_VERSION_FLOAT < 9.0) static let iOS9 = (iOSVersion.SYS_VERSION_FLOAT >= 9.0 && iOSVersion.SYS_VERSION_FLOAT < 10.0) }
Kastor