Как определить версию ОС во время выполнения в 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);
}
Ответы
Ответ 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
и ручному отображению, как описано в этом ответе в противном случае.