Как определить версию ОС во время выполнения в OS X или iOS (без использования Gestalt)?


функция Gestalt (), расположенная в CarbonCore/OSUtils.h был устаревшим с OS X 10.8 Mountain Lion.

Я часто использую эту функцию для тестирования версии операционной системы OS X во время выполнения (см. пример игрушки ниже).

какой другой API можно использовать для проверки версии операционной системы OS X во время выполнения в приложении Cocoa?

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

    printf("OS X Version: %d.%d.%dn", versMaj, versMin, versBugFix);
}
12 62

12 ответов:

на OS X 10.10 (и iOS 8.0), вы можете использовать [[NSProcessInfo processInfo] operatingSystemVersion] который возвращает a NSOperatingSystemVersion структура, определяемая как

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

существует также метод в NSProcessInfo, который будет делать сравнение для вас:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

будьте осторожны, хотя документально доступны в OS X 10.10 и более поздних версиях, оба operatingSystemVersion и isOperatingSystemAtLeastVersion: существует на OS X 10.9 (наверное 10.9.2) и работает, как ожидалось. Это означает, что вы не должны проверить, если NSProcessInfo реагирует на эти селекторы чтобы проверить, если вы работаете на OS X 10.9 или 10.10.

на iOS эти методы эффективно доступны только с iOS 8.0.

в командной строке:

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

программно:

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

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

версия Darwin для выпуска 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

образец для получения и тестирования версий:

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


}

результат на моей машине macOs High Sierra 10.13.2

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

существует значение NSAppKitVersionNumber, которое вы можете использовать для проверки различных версий AppKit, хотя они не соответствуют точно версиям ОС

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

есть какао API. Вы можете получить строку версии os X из класса NSProcessInfo.

ниже приведен код для получения строки версии операционной системы..

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

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

// ===>> версия 10.8.2 (Build 12C2034) значение результата

Это не не рекомендуется.

существует также kCFCoreFoundationVersionNumber, который может быть использован, если вам нужно только проверить минимальную версию для поддержки. Это имеет то преимущество, что он работает с 10.1 и может быть выполнен в C, C++ и Objective-C.

например, чтобы проверить 10.10 или больше:

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

вам нужно будет связать с каркасом CoreFoundation (или Foundation).

Он также работает в Swift точно так же. Вот еще один пример:

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.")
}

или, проще говоря, вот код:

NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
NSString *productVersion = [version objectForKey:@"ProductVersion"];
NSLog (@"productVersion =========== %@", productVersion);

Я надеюсь, что это кому-то поможет.

вы можете легко получить основную, второстепенную, патч-версию операционной системы с помощью 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];

вот что я использую:

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");
}

рекомендуется Примечания К Выпуску AppKit

Чтение / Система / Библиотека/CoreServices / SystemVersion.plist-это не возможно, если приложение является изолированное

Если у вас есть приложение, которое нужно запустить на 10.10, а также предыдущие версии, вот решение:

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
}

обратите внимание, что даже 10.9, похоже, отвечает на селектор operatingSystemVersion, поэтому я думаю, что это просто частный API в 10.9 (но все еще работает).

это работает на всех версиях OS X и не полагается на синтаксический анализ строк или файловый ввод-вывод

здесь uname(3):

The uname() функция хранит нулевые строки информации, идентифицирующие текущую систему в структуре, на которую ссылается name.

The utsname структура определяется в <sys/utsname.h> заголовочный файл, и содержит следующие элементы:

  • sysname - имя реализация операционной системы.
  • nodename - сетевое имя этой машины.
  • release - уровень выпуска операционной системы.
  • version - версия операционной системы.
  • machine - аппаратной платформы машины.

это на самом деле компиляция ответов выше, с некоторым дальнейшим руководством для нуждающегося разработчика.

OS-X предоставляет свою версию во время выполнения несколькими способами. Каждый способ лучше подходит для конкретного сценария развития. Я постараюсь обобщить их все и надеюсь, что другие завершат мой ответ, если я что-то забыл.

во-первых, полный список способов получения версии ОС.

  1. The инструмент и функция предоставляет версию ОС unix (darwin). Хотя это не маркетинговая версия ОС, она согласована с ней однозначно, поэтому вы можете вывести из нее маркетинговую версию OS-X.
  2. sysctl kern.osrelease командная строка (или sysctlbyname("kern.osrelease", str, &size, NULL, 0) функция) предоставит ту же информацию, что и uname, незначительно легче разобрать.
  3. Gestalt(gestaltSystemVersionMajor) (С "Minor" и BugFix" варианты самые старые (пре-углерод!) API, чтобы получить версию маркетинговой ОС, по-прежнему поддерживается давно устаревшим. Доступно в C из фреймворка CoreServices, но не рекомендуется.
  4. NSAppKitVersionNumber является плавающей константой фреймворка AppKit, которая обеспечит версию OS-X Appkit (выровненную с версией ОС), доступную для всех приложений, которые ссылаются на AppKit. Он также обеспечивает полное перечисление всех возможных версий (например,NSAppKitVersionNumber10_7_2)
  5. kCFCoreFoundationVersionNumber в рамках CoreFoundation флоат-постоянная, одинаковая для Appkit коллеги, доступен для всех приложений, связанных против CoreFoundation, как в C, Obj-C, так и в Swift. Он также обеспечивает полное перечисление всех выпущенных версий OS X (например,kCFCoreFoundationVersionNumber10_9)
  6. [[NSProcessInfo processInfo] operatingSystemVersionString]; это API Cocoa, доступный в Obj-C для приложений OS-X и iOS.
  7. есть ресурс .plist в /System/Library/CoreServices/SystemVersion.plist который среди прочего содержит версию ОС в ключе "ProductVersion". NSProcessInfo считывает информацию из этого файла, но вы можете сделать это непосредственно с помощью вашего plist-reading API выбор.

для получения более подробной информации о каждом варианте - пожалуйста, обратитесь к ответам выше. Там полно информации!

поздно к игре, но я в конечном итоге здесь ищет ответ, а также. Для чего это стоит, может это для кого-то другого;

в прошлом я использовал подход командной строки:

sw_vers

что приводит к:

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

каждая строка может быть запрошена индивидуально (помните нотацию camelback):

sw_vers -productVersion
10.13.6

sw_vers -productName
Mac OS X

sw_vers -buildVersion
17G65

сказав, что спасибо за все другие решения, перечисленные здесь ...