Подтвердить что ты не робот

Как определить версию ОС во время выполнения в 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.%d\n", versMaj, versMin, versBugFix);
}
4b9b3361

Ответ 1

В OS X 10.10 (и iOS 8.0) вы можете использовать [[NSProcessInfo processInfo] operatingSystemVersion], который возвращает структуру 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.

Ответ 2

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

$ 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

Ответ 3

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

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

Ответ 4

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

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

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

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

//=== → Значение результата 10.8.2 (Build 12C2034)

Он не устарел.

Ответ 5

Существует также kCFCoreFoundationVersionNumber, который можно использовать, если вам нужно только проверить минимальную версию для поддержки. Это имеет то преимущество, что он работает с 10.1 и может выполняться в 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.")
}

Ответ 6

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

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

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

Ответ 7

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

Ответ 8

Если у вас есть приложение, которое нужно запустить на 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 (но все еще работает).

Это работает во всех версиях ОС X и не зависит от анализа строк или ввода/вывода файлов.

Ответ 9

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

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

Чтение/System/Library/CoreServices/SystemVersion.plist невозможно, если приложение изолировано.

Ответ 10

Там uname(3):

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

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

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

Ответ 11

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

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

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

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

Подробнее о каждом варианте см. выше. Там много информации!

Ответ 12

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

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

sw_vers

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

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

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

sw_vers -productVersion
10.13.6

sw_vers -productName
Mac OS X

sw_vers -buildVersion
17G65

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

Ответ 13

Играя с sysctl на macOS сегодня, я наткнулся на kern.osproductversion который действительно содержит текущую версию ОС. На моем Mac под управлением Mojave я получаю:

$ sysctl kern.osproductversion
kern.osproductversion: 10.14.3

Конечно, это значение можно получить программно:

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

Эта фиксация базы кода ядра xnu указывает на то, что osproductversion является недавним дополнением, появившимся в середине 2018 года. Я успешно протестировал его на 10.14.3 и 10.13.6.

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