位于CarbonCore/OSUtils.h
的Gestalt()函数自OS X 10.8 Mountain Lion起已被弃用。
我经常使用此函数在运行时测试OS X操作系统的版本(参见下面的玩具示例)。
在Cocoa应用程序中,可以使用哪些其他API在运行时检查OS X操作系统版本?
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);
}
在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及更高版本中可用,但是OS X 10.9(operatingSystemVersion
)上存在isOperatingSystemAtLeastVersion:
和probably 10.9.2,并且按预期工作。这意味着您不能测试NSProcessInfo
是否响应这些选择器以检查您是否在OS X 10.9或10.10上运行。
在iOS上,这些方法实际上仅在iOS 8.0之后可用。
有uname(3)
:
qazxsw poi函数存储以null结尾的信息字符串,用于将当前系统标识为
uname()
引用的结构。
name
结构在utsname
头文件中定义,包含以下成员:
<sys/utsname.h>
- 操作系统实现的名称。sysname
- 本机的网络名称。nodename
- 操作系统的发布级别。release
- 操作系统的版本级别。version
- 机器硬件平台。
这实际上是上面答案的汇编,有一些进一步指导有需要的开发人员。
OS-X以多种方式在运行时提供其版本。每种方式都更适合特定的开发方案。我会试着总结一下,如果我忘记了什么,希望别人能完成我的答案。
首先,获取操作系统版本的综合方法列表。
machine
命令行工具和函数提供了操作系统的unix(darwin)版本。虽然这不是操作系统的营销版本,但它与其唯一对齐,因此您可以从中推断出OS-X营销版本。uname
命令行(或sysctl kern.osrelease
函数)将提供与uname相同的信息,稍微容易解析。sysctlbyname("kern.osrelease", str, &size, NULL, 0)
(其“Gestalt(gestaltSystemVersionMajor)
”和Minor
“变体是获得营销操作系统版本的最古老的(前碳!)API,仍然受到长期弃用的支持。可从CoreServices框架获得C,但不推荐。BugFix
是AppKit框架的浮点常量,它将提供OS-X Appkit版本(与操作系统版本一致),可用于链接AppKit的所有应用程序。它还提供了所有可能版本的全面列举(例如NSAppKitVersionNumber
)NSAppKitVersionNumber10_7_2
是一个CoreFoundation框架浮点常量,与Appkit对应相同,可用于所有与CoreFoundation链接的应用程序,包括C,Obj-C和Swift。它也提供了所有OS X发布版本的全面枚举(例如kCFCoreFoundationVersionNumber
)kCFCoreFoundationVersionNumber10_9
是Obj-C中可用于OS-X和iOS应用程序的Cocoa API。[[NSProcessInfo processInfo] operatingSystemVersionString];
中有一个资源.plist,其中包含“ProductVersion”键中的操作系统版本。 NSProcessInfo从此文件中读取其信息,但您可以使用您选择的PList-reading API直接执行此操作。有关每个选项的更多详细信息 - 请参阅上面的答案。那里有很多信息!
今天在MacOS上玩/System/Library/CoreServices/SystemVersion.plist
的时候我偶然发现了sysctl
,它确实包含了当前的操作系统版本。在运行Mojave的Mac上,我得到:
kern.osproductversion
当然,也可以通过编程方式检索该值:
$ 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内核代码库表明This commit是2018年中期出现的最新成员。我在10.14.3和10.13.6上成功测试了它。
总而言之,我认为最好的程序化,非Cocoa方法是检查osproductversion
是否产生有效结果并回退到kern.osproductversion
和kern.osrelease
中描述的手动映射。
比赛结束,但我最终在这里寻找答案。对于它的价值,也许它可以用于其他人;
在过去,我使用命令行方法:
this answer
结果如下:
sw_vers
可以单独询问每一行(请注意驼峰符号):
ProductName: Mac OS X
ProductVersion: 10.13.6
BuildVersion: 17G65
话虽如此,感谢此处列出的所有其他解决方案......
在命令行上:
$ 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");
}
有一个cocoa API。您可以从NSProcessInfo类获取os X版本字符串。
获取操作系统版本字符串的代码如下:
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.")
}
您可以使用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];
或者,更简单地说,这是代码:
NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
NSString *productVersion = [version objectForKey:@"ProductVersion"];
NSLog (@"productVersion =========== %@", productVersion);
我希望这可以帮助别人。
如果您的应用程序需要在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选择器,所以我认为它只是10.9中的私有API(但仍然有效)。
这适用于所有版本的OS X,不依赖于字符串解析或文件I / O.
这是我使用的:
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");
}
如果应用程序是沙盒,则无法读取/System/Library/CoreServices/SystemVersion.plist