79 votes

Comment puis-je déterminer la version du système d'exploitation au moment de l'exécution dans OS X ou iOS (sans utiliser Gestalt) ?

La fonction Gestalt() située dans CarbonCore/OSUtils.h a été déprécié à partir de OS X 10.8 Mountain Lion.

J'utilise souvent cette fonction pour tester la version du système d'exploitation OS X au moment de l'exécution (voir l'exemple de jouet ci-dessous).

Quelle autre API pourrait être utilisée pour vérifier la version du système d'exploitation OS X au moment de l'exécution dans une application Cocoa ?

int main() {
    SInt32 versMaj, versMin, versBugFix;
    Gestalt(gestaltSystemVersionMajor, &versMaj);
    Gestalt(gestaltSystemVersionMinor, &versMin);
    Gestalt(gestaltSystemVersionBugFix, &versBugFix);

    printf("OS X Version: %d.%d.%d\n", versMaj, versMin, versBugFix);
}

1 votes

Il y a une discussion sur la même chose dans cette question : stackoverflow.com/questions/11055146/

0 votes

Les API de Gestalt sont TRÈS anciennes (en fait, elles datent d'avant le carbone) et sont pour la plupart dépréciées. Bien qu'elles soient encore maintenues et qu'elles fonctionnent, ce n'est pas une bonne idée de les utiliser de nos jours. Pas même pour la version runtime...

77voto

0xced Points 10972

Sous OS X 10.10 (et iOS 8.0), vous pouvez utiliser [[NSProcessInfo processInfo] operatingSystemVersion] qui renvoie un NSOperatingSystemVersion struct, définie comme suit

typedef struct {
    NSInteger majorVersion;
    NSInteger minorVersion;
    NSInteger patchVersion;
} NSOperatingSystemVersion;

Il existe également une méthode dans NSProcessInfo qui fera la comparaison pour vous :

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Méfiez-vous de bien qu'il soit documenté pour être disponible dans OS X 10.10 et plus, les deux operatingSystemVersion y isOperatingSystemAtLeastVersion: existent sur OS X 10.9 ( probablement 10.9.2 ) et fonctionnent comme prévu. Cela signifie que vous ne devez pas tester si NSProcessInfo répond à ces sélecteurs pour vérifier si vous êtes sous OS X 10.9 ou 10.10.

Sur iOS, ces méthodes ne sont effectivement disponibles que depuis iOS 8.0.

2 votes

Vous pouvez également utiliser la catégorie Objective-C suivante (sous licence BSD) pour utiliser ces nouvelles méthodes sur des versions plus anciennes du système d'exploitation : github.com/petroules/CocoaBackports/blob/master/CocoaBackports/ Il devrait fonctionner jusqu'à OS X 10.5 et iOS 2.0 avec MRC, ARC ou GC et avec les anciens SDK.

0 votes

Notez que cela renverra la version d'OS X si vous exécutez l'application dans le simulateur iOS.

1 votes

À partir de la version bêta 4 d'iOS 8, la fonction operatingSystemVersion renvoie la version correcte lorsqu'elle est exécutée dans le simulateur iOS.

27voto

Sur la ligne de commande :

$ sysctl kern.osrelease
kern.osrelease: 12.0.0
$ sysctl kern.osversion
kern.osversion: 12A269

De manière programmée :

#include <errno.h>
#include <sys/sysctl.h>

char str[256];
size_t size = sizeof(str);
int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0);

Version Darwin à la version OS X :

17.x.x. macOS 10.13.x High Sierra
16.x.x  macOS 10.12.x Sierra
15.x.x  OS X  10.11.x El Capitan
14.x.x  OS X  10.10.x Yosemite
13.x.x  OS X  10.9.x  Mavericks
12.x.x  OS X  10.8.x  Mountain Lion
11.x.x  OS X  10.7.x  Lion
10.x.x  OS X  10.6.x  Snow Leopard
 9.x.x  OS X  10.5.x  Leopard
 8.x.x  OS X  10.4.x  Tiger
 7.x.x  OS X  10.3.x  Panther
 6.x.x  OS X  10.2.x  Jaguar
 5.x    OS X  10.1.x  Puma

Un échantillon pour obtenir et tester les versions :

#include <string.h>
#include <stdio.h>
#include <sys/sysctl.h>

/* kernel version as major minor component*/
struct kern {
    short int version[3];
};

/* return the kernel version */
void GetKernelVersion(struct kern *k) {
   static short int version_[3] = {0};
   if (!version_[0]) {
      // just in case it fails someday
      version_[0] = version_[1] = version_[2] = -1;
      char str[256] = {0};
      size_t size = sizeof(str);
      int ret = sysctlbyname("kern.osrelease", str, &size, NULL, 0);
      if (ret == 0) sscanf(str, "%hd.%hd.%hd", &version_[0], &version_[1], &version_[2]);
    }
    memcpy(k->version, version_, sizeof(version_));
}

/* compare os version with a specific one
0 is equal
negative value if the installed version is less
positive value if the installed version is more
*/
int CompareKernelVersion(short int major, short int minor, short int component) {
    struct kern k;
    GetKernelVersion(&k);
    if ( k.version[0] !=  major) return major - k.version[0];
    if ( k.version[1] !=  minor) return minor - k.version[1];
    if ( k.version[2] !=  component) return component - k.version[2];
    return 0;
}

int main() {
   struct kern kern;
   GetKernelVersion(&kern);
   printf("%hd %hd %hd\n", kern.version[0], kern.version[1], kern.version[2]);

   printf("up: %d %d eq %d %d low %d %d\n",
        CompareKernelVersion(17, 0, 0), CompareKernelVersion(16, 3, 0),
        CompareKernelVersion(17, 3, 0), CompareKernelVersion(17,3,0),
        CompareKernelVersion(17,5,0), CompareKernelVersion(18,3,0));

}

Résultat sur ma machine macOs High Sierra 10.13.2

17 3 0
up: -3 -1 eq 0 0 low 2 1

1 votes

Notez que ce sont les mêmes résultats que vous obtenez à partir de uname (discuté dans la réponse de Carl Norum). Il s'agit de numéros de version du noyau, qui correspondent quelque peu aux versions du système d'exploitation, mais pas de manière évidente.

4 votes

Ne l'utilisez jamais pour déterminer la version d'OS X ou d'iOS. Bien que vous puissiez déterminer arithmétiquement une version à partir d'une autre pour OS X à l'heure actuelle, il n'est pas garanti qu'une telle comparaison fonctionne à l'avenir. À titre d'exemple concret, une version d'iOS a déjà sauté une version de Darwin ; la même chose pourrait se produire avec OS X.

26voto

iain Points 3778

Il existe la valeur NSAppKitVersionNumber que vous pouvez utiliser pour vérifier les différentes versions d'AppKit, bien qu'elles ne correspondent pas exactement aux versions du système d'exploitation.

if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_7_2) {
    NSLog (@"We are not running on Mountain Lion");
}

4 votes

C'est également ce qu'implique la documentation officielle ici (au point "Vérification de la version d'exécution") : developer.apple.com/library/mac/#releasenotes/Cocoa/AppKit.html

20voto

DHL Points 111

Il existe une API pour le cacao. Vous pouvez obtenir une chaîne de version os X à partir de la classe NSProcessInfo.

Le code pour obtenir la chaîne de la version du système d'exploitation est le suivant

NSString * operatingSystemVersionString = [[NSProcessInfo processInfo] operatingSystemVersionString];

NSLog(@"operatingSystemVersionString => %@" , operatingSystemVersionString);

// ===>> Version 10.8.2 (Build 12C2034) valeur du résultat

Il n'est pas déprécié.

0 votes

La 10.10 ajoute un moyen de les récupérer de manière structurée (littéralement), mais vous ne pouvez l'utiliser que si vous ciblez le SDK 10.10. Ce qui va plutôt à l'encontre du but recherché, pour le moment. Vous pouvez toujours utiliser Gestalt() pour le moment, mais il est déprécié et pourrait disparaître à tout moment.

0 votes

Cela POURRAIT être génial. Il n'est pas déprécié et fonctionne sur le sdk 10.2+... Malheureusement, la documentation Apple dit The operating system version string is human readable, localized, and is appropriate for displaying to the user. This string is not appropriate for parsing. developer.apple.com/reference/foundation/nsprocessinfo/

1 votes

La réponse de @Vikas Bansal est sans doute meilleure.

8voto

SentientAI Points 103

Si vous avez une application qui doit fonctionner sur la version 10.10 ainsi que sur les versions antérieures, voici une solution :

typedef struct {
        NSInteger majorVersion;
        NSInteger minorVersion;
        NSInteger patchVersion;
} MyOperatingSystemVersion;

if ([[NSProcessInfo processInfo] respondsToSelector:@selector(operatingSystemVersion)]) {
    MyOperatingSystemVersion version = ((MyOperatingSystemVersion(*)(id, SEL))objc_msgSend_stret)([NSProcessInfo processInfo], @selector(operatingSystemVersion));
    // do whatever you want with the version struct here
}
else {
    UInt32 systemVersion = 0;
    OSStatus err = Gestalt(gestaltSystemVersion, (SInt32 *) &systemVersion);
    // do whatever you want with the systemVersion as before
}

Notez que même la 10.9 semble répondre au sélecteur operatingSystemVersion, donc je pense que c'était juste une API privée dans la 10.9 (mais qui fonctionne toujours).

Cela fonctionne sur toutes les versions d'OS X et ne dépend pas de l'analyse des chaînes de caractères ou des entrées/sorties de fichiers.

7 votes

N'utilisez PAS gestaltSystemVersion ! Cela échouera si l'un des composants de la version est supérieur à 9. Par exemple, OS X 10.4.11 sera retourné comme 10.4.9. A la place, récupérez chaque composant de version individuellement en utilisant gestaltSystemVersionMajor, gestaltSystemVersionMinor, et gestaltSystemVersionBugFix.

2 votes

Juste pour info, c'est toujours hace s'appuient sur les E/S de fichiers en interne... les deux méthodes liront SystemVersion.plist à chaque fois qu'elles seront appelées (pas de mise en cache).

1 votes

Pour une raison quelconque, faire le respondsToSelector vérifier operatingSystemVersion retourne OUI même si je suis sur Mavericks.

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