908 votes

Comment vérifier la version d'iOS ?

Je veux vérifier si le iOS de l'appareil est supérieure à 3.1.3 J'ai essayé des choses comme :

[[UIDevice currentDevice].systemVersion floatValue]

mais cela ne fonctionne pas, je veux juste un :

if (version > 3.1.3) { }

Comment puis-je y parvenir ?

7 votes

Note du modérateur : Au fil du temps, cette question a accumulé plus de 30 réponses. Avant d'ajouter une nouvelle réponse, soyez sûr que votre solution n'a pas déjà été fournie.

5 votes

Démarrer Xcode 7, if #available(iOS 9, *) {} dans Swift. Démarrer Xcode 9, if (@available(iOS 11, *)) {} en objective-c.

0 votes

1060voto

yasirmturk Points 935
/*
 *  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")) {
    ...
}

21 votes

+1. La solution la plus simple à laquelle je pense est de conserver ces informations dans un en-tête que vous pouvez inclure si nécessaire. Dans plusieurs cas, c'est plus fiable que de vérifier la disponibilité en utilisant NSClassFromString. Un autre exemple est celui d'iAd, où si vous utilisez ADBannerContentSizeIdentifierPortrait dans une version antérieure à 4.2, vous obtiendrez EXEC_BAD_ACCESS, mais l'équivalent ADBannerContentSizeIdentifier320x50 est déprécié après 4.1.

1 votes

Je l'utilise également avec UIPageViewController et en définissant le style à UIPageViewControllerTransitionStyleScroll dans iOS6.

0 votes

C'est parfait, cela devrait être la réponse acceptée. J'ajouterais juste que pour les méthodes uniquement pour les versions supérieures à la version de base, il faut quand même vérifier en utilisant respondsToSelector .

1051voto

Justin Points 9636

La réponse rapide

À partir de Swift 2.0, vous pouvez utiliser #available dans un if o guard pour protéger le code qui ne doit être exécuté que sur certains systèmes.

if #available(iOS 9, *) {}

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

[[NSProcessInfo processInfo] operatingSystemVersion] dans iOS 8 et plus.

A partir de Xcode 9 :

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

La réponse complète

En Objective-C, et en Swift dans de rares cas, il vaut mieux éviter de se fier à la version du système d'exploitation comme indication des capacités du périphérique ou du système d'exploitation. Il existe généralement une méthode plus fiable pour vérifier si une fonctionnalité ou une classe particulière est disponible.

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

Par exemple, vous pouvez vérifier si UIPopoverController est disponible sur l'appareil actuel en utilisant NSClassFromString :

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

Pour les classes faiblement liées, il est prudent d'envoyer un message à la classe, directement. Notamment, cela fonctionne pour les frameworks qui ne sont pas explicitement liés comme "Required". Pour les classes manquantes, l'expression est évaluée à nil, ce qui fait échouer la condition :

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

Certaines classes, comme CLLocationManager y UIDevice , fournissent des méthodes pour vérifier les capacités des dispositifs :

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. Ceci est apparu dans iOS 8 avec l'introduction de la fonction UIApplicationOpenSettingsURLString utilisé pour charger l'application Settings via -openURL: . Cette valeur n'existait pas avant iOS 8. Passer nil à cette API provoquera un plantage, vous devez donc prendre soin de vérifier d'abord l'existence de la constante :

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

Comparaison avec 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 visant iOS 8 et plus, NSProcessInfo comprend une méthode permettant d'effectuer des comparaisons de versions avec moins de risques d'erreur :

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Les projets visant des systèmes plus anciens peuvent utiliser systemVersion sur UIDevice . Apple l'utilise dans son GLSprite exemple de code.

// 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 systemVersion est ce que vous voulez, assurez-vous de le traiter comme une chaîne de caractères ou vous risquez de tronquer le numéro de révision du patch (ex. 3.1.2 -> 3.1).

163 votes

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 en 3.x sont devenues publiques en 4.0, donc si vous vérifiez simplement leur disponibilité, vous obtiendrez un résultat erroné en 3.x. De plus, la façon dont les UIScrollViews gèrent les échelles de zoom a subtilement changé en 3.2 et plus, donc vous devrez vérifier les versions du système d'exploitation afin de traiter les résultats de façon appropriée.

2 votes

IOS 3.2 ne semble pas envoyer -viewWillAppear dans un UISplitViewController . Mon hack est de déterminer si < iOS 4.0, et de l'envoyer moi-même au contrôleur de la vue détaillée dans la vue racine. -didSelectRowAtIndexPath .

10 votes

Vous devez être un peu plus prudent ici car [@"10.0" compare:@"10" options:NSNumericSearch] renvoie à NSOrderedDescending ce qui pourrait bien ne pas être voulu du tout. (Je pourrais m'attendre à ce que NSOrderedSame .) C'est au moins une possibilité théorique.

253voto

CarlJ Points 5080

Comme le suggère le Documents officiels d'Apple : vous pouvez utiliser le NSFoundationVersionNumber à partir du NSObjCRuntime.h fichier d'en-tête.

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    // here you go with iOS 7
}

42 votes

+1 C'est en fait le le plus sûr et l'option la plus précise ici.

8 votes

Hum NSFoundationVersionNumber_iOS_6_1 n'existe pas dans le SDK iOS 5.

0 votes

@Nate J'utilise moi-même iOS 7 SKD. Ce que j'ai fait maintenant est de vérifier si NSFoundationVersionNumber_iOS_6_1 défini ou non, si non, bien sûr c'est en dessous d'iOS 7. Je dois considérer ce cas parce que je dois m'assurer que la librairie est adaptée à tous les développeurs, y compris ceux qui utilisent encore le SDK iOS 5. Quoi qu'il en soit, c'est une bonne solution, je suis d'accord avec elle. C'est pourquoi je l'utilise ;)

39voto

Jonathan Grynspan Points 32291

Essayez :

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
}

2 votes

Pourquoi ne pas inverser l'ordre ici et économiser une comparaison, puisque @"3.1.3" et systemVersion sont tous deux des NSStrings ? Ie : ` if ([@"3.1.3" compare : [UIDevice currentDevice].systemVersion options : NSNumericSearch] == NSOrderedDescending) ;// Version du système d'exploitation >= 3.1.3 else ;// Version du système d'exploitation < 3.1.3``.

3 votes

Cela pourrait rendre la logique moins claire. L'opération devrait cependant être équivalente.

1 votes

Une comparaison entre deux entiers n'est sûrement pas très coûteuse.

35voto

Daniel Galasko Points 485

Approche privilégiée

Dans Swift 2.0, Apple a ajouté le contrôle de disponibilité en utilisant une syntaxe beaucoup plus pratique (Lire la suite aquí ). Maintenant vous pouvez 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
}

Il s'agit de la préférence par rapport à la vérification respondsToSelector etc ( Quoi de neuf dans Swift ). Maintenant, le compilateur vous avertira toujours si vous ne protégez pas votre code correctement.


Pré Swift 2.0

Les nouveautés d'iOS 8 sont les suivantes NSProcessInfo permettant une meilleure vérification sémantique des versions.

Déploiement sur iOS 8 et supérieur

Pour des objectifs de déploiement minimum de iOS 8.0 ou plus, utilisez NSProcessInfo operatingSystemVersion o 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 des objectifs de déploiement minimum de iOS 7.1 ou en dessous, utiliser comparer wi NSStringCompareOptions.NumericSearch sur 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 à NSHipster .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X