Jak określić wersję systemu operacyjnego w systemie OS X lub iOS (bez użycia Gestalt)?

Funkcja Gestalt() znajdująca się w CarbonCore/OSUtils.h została wycofana z systemu OS X 10.8 Mountain Lion.

Często używam tej funkcji do testowania wersji systemu operacyjnego OS X w czasie wykonywania (zobacz przykład poniżej).

Jakie inne API można wykorzystać do sprawdzenia wersji systemu operacyjnego OS X w aplikacji 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);
}
Author: 0xced, 2012-06-17

12 answers

Na OS X 10.10 (i iOS 8.0) możesz użyć [[NSProcessInfo processInfo] operatingSystemVersion], która zwraca strukturę NSOperatingSystemVersion zdefiniowaną jako

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

Istnieje również metoda w NSProcessInfo, która zrobi porównanie za ciebie:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Strzeżcie się , chociaż udokumentowane, że są dostępne w OS X 10.10 i późniejszych, zarówno operatingSystemVersion, jak i isOperatingSystemAtLeastVersion: istnieją na OS X 10.9 (prawdopodobnie 10.9.2) i działają zgodnie z oczekiwaniami. Oznacza to, że nie wolno sprawdzać, czy NSProcessInfo odpowiada na te selektory, aby sprawdzić, czy działasz na OS X 10.9 lub 10.10.

W systemie iOS metody te są dostępne tylko od wersji IOS 8.0.
 58
Author: 0xced,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-10 11:40:48

W wierszu poleceń:

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

Programowo:

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

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

Wersja Darwina do wydania 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

Próbka do pobrania i przetestowania wersji:

#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));


}

Wynik na moim komputerze macOs High Sierra 10.13.2

17 3 0
up: -3 -1 eq 0 0 low 2 1
 26
Author: Variable Length Coder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-18 14:02:08

Istnieje wartość NSAppKitVersionNumber, której możesz użyć do sprawdzenia różnych wersji AppKit, chociaż nie odpowiadają one dokładnie wersjom systemu operacyjnego

if (NSAppKitVersionNumber <= NSAppKitVersionNumber10_7_2) {
    NSLog (@"We are not running on Mountain Lion");
}
 22
Author: iain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-28 00:45:49

Istnieje API cocoa. Możesz uzyskać ciąg wersji os X z klasy NSProcessInfo.

Kod, aby uzyskać ciąg wersji systemu operacyjnego znajduje się poniżej..

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

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

// ===>> Wersja 10.8.2 (Build 12c2034) wartość wyniku

To nie jest przestarzałe.

 16
Author: DHL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-05 09:13:54

Istnieje również kCFCoreFoundationVersionNumber, który może być użyty, jeśli potrzebujesz tylko sprawdzić minimalną wersję do obsługi. Ma to tę zaletę, że działa wstecz do wersji 10.1 i można to zrobić w C, C++ i Objective-C. {]}

Na przykład, aby sprawdzić dla 10.10 lub większej:

#include <CoreFoundation/CoreFoundation.h>
if (floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9) {
    printf("On 10.10 or greater.");
}

Będziesz musiał połączyć się ze strukturą Fundacji (CoreFoundation).

Działa również w języku Swift w dokładnie taki sam sposób. Oto kolejny przykład:

import Foundation
if floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_8 {
    println("On 10.9 or greater.")
} else if floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9 {
    println("On 10.10 or greater.")
}
 11
Author: kainjow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 21:57:08

Lub, mówiąc prościej, oto kod:

NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
NSString *productVersion = [version objectForKey:@"ProductVersion"];
NSLog (@"productVersion =========== %@", productVersion);
Mam nadzieję, że to komuś pomoże.
 9
Author: Winston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-22 15:13:12

Możesz łatwo uzyskać główną, podrzędną wersję systemu operacyjnego za pomocą NSOperatingSystemVersion

NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];

NSString* major = [NSString stringWithFormat:@"%d", version.majorVersion];


NSString* minor = [NSString stringWithFormat:@"%d", version.minorVersion];


NSString* patch = [NSString stringWithFormat:@"%d", version.patchVersion];
 9
Author: Vikas Bansal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-13 07:54:27

Tego używam:

NSInteger osxVersion;
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_6) {
    //10.6.x or earlier systems
    osxVersion = 106;
    NSLog(@"Mac OSX Snow Leopard");
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_7) {
    /* On a 10.7 - 10.7.x system */
    osxVersion = 107;
    NSLog(@"Mac OSX Lion");
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_8) {
    /* On a 10.8 - 10.8.x system */
    osxVersion = 108;
    NSLog(@"Mac OSX Moutain Lion");
} else {
    /* 10.9 or later system */
    osxVersion = 109;
    NSLog(@"Mac OSX: Mavericks or Later");
}
To jest zalecane w AppKit Release Notes

Reading/System/Library/CoreServices / SystemVersion.plist nie jest możliwe, jeśli aplikacja jest piaskownica

 6
Author: Tibidabo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-29 08:38:12

Jeśli masz aplikację, która musi działać w wersji 10.10, jak również w poprzednich wersjach, oto rozwiązanie:

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
}

Zauważ, że nawet 10.9 wydaje się odpowiadać selektorowi operat systemversion, więc myślę, że to było tylko prywatne API w 10.9 (ale nadal działa).

Działa to na wszystkich wersjach OS X i nie polega na parsowaniu łańcuchów znaków lub We/Wy pliku.

 6
Author: SentientAI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-12 13:32:45

Jest uname(3):

The uname() funkcja przechowuje zakończone nul ciągi informacji identyfikujących bieżący system w strukturze, do której odwołuje się name.

The utsname struktura jest zdefiniowana w <sys/utsname.h> plik nagłówkowy oraz zawiera następujących członków:

  • sysname - Nazwa implementacji systemu operacyjnego.
  • nodename - Nazwa sieciowa tego urządzenia.
  • release - poziom Release systemu operacyjnego.
  • version - poziom wersji systemu operacyjnego.
  • machine - Platforma sprzętowa Maszyny.
 5
Author: Carl Norum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-18 00:29:02

Jest to tak naprawdę kompilacja powyższych odpowiedzi, z pewnymi dalszymi wskazówkami dla deweloperów w potrzebie.

OS-X udostępnia swoją wersję w trybie runtime na kilka sposobów. Każdy sposób lepiej pasuje do konkretnego scenariusza rozwoju. Postaram się podsumować je wszystkie i mam nadzieję, że inni uzupełnią moją odpowiedź, jeśli o czymś zapomniałem.

Po pierwsze, obszerna lista sposobów uzyskania wersji systemu operacyjnego.

  1. narzędzie i funkcja wiersza poleceń uname dostarcza Uniksa (darwin) wersja systemu operacyjnego. Chociaż nie jest to wersja marketingowa systemu operacyjnego, jest z nim dopasowana wyjątkowo, więc można wywnioskować z niego wersję marketingową OS-X.
  2. sysctl kern.osrelease wiersz poleceń (lub Funkcja sysctlbyname("kern.osrelease", str, &size, NULL, 0)) dostarczy te same informacje co uname, nieznacznie łatwiejsze do przetworzenia.
  3. Gestalt(gestaltSystemVersionMajor) (z wariantami "Minor "i BugFix" jest najstarszy (pre-Carbon!) API, aby uzyskać wersję marketingową systemu operacyjnego, nadal obsługiwaną przez długo przestarzałą. Dostępne w C z frameworka CoreServices, ale nie polecam.
  4. NSAppKitVersionNumber jest stałą zmiennoprzecinkową frameworka AppKit, która zapewni wersję OS-X Appkit (dostosowaną do wersji OS), dostępną dla wszystkich aplikacji, które łączą się z AppKit. Zawiera również obszerne wyliczenie wszystkich możliwych wersji (np. NSAppKitVersionNumber10_7_2)
  5. kCFCoreFoundationVersionNumber jest stałą floatową frameworka CoreFoundation, identyczną z odpowiednikiem Appkit, dostępną dla wszystkich aplikacji połączonych z CoreFoundation, zarówno w C, Obj-C, jak i Swift. To również zapewnia wszystkie wersje systemu OS X (np. kCFCoreFoundationVersionNumber10_9)
  6. [[NSProcessInfo processInfo] operatingSystemVersionString]; to API Cocoa dostępne w Obj - C zarówno dla aplikacji OS-X, jak i iOS.
  7. istnieje zasób .plist w /System/Library/CoreServices/SystemVersion.plist, który między innymi zawiera wersję systemu operacyjnego w kluczu "ProductVersion". NSProcessInfo odczytuje swoje informacje z tego pliku, ale możesz to zrobić bezpośrednio za pomocą wybranego API do odczytu PList.

Aby uzyskać więcej informacji na temat każdej opcji-zapoznaj się z odpowiedziami powyżej. Jest tam mnóstwo informacji!

 5
Author: Motti Shneor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-18 09:55:19

Spóźniłem się na mecz, ale wylądowałem tutaj, szukając odpowiedzi. Jeśli to coś warte, może przyda się komuś innemu;

W przeszłości używałem podejścia wiersza poleceń:

sw_vers

Co daje:

ProductName:    Mac OS X
ProductVersion: 10.13.6
BuildVersion:   17G65

Każdy wiersz może być zapytany indywidualnie (pamiętaj o notacji camelback):

sw_vers -productVersion
10.13.6

sw_vers -productName
Mac OS X

sw_vers -buildVersion
17G65

Powiedziawszy to, dziękuję za wszystkie inne rozwiązania wymienione tutaj ...

 0
Author: Hanzaplastique,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 17:27:00