如何在 OS X 或 iOS 中确定运行时的操作系统版本(不使用格式塔)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11072804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 18:50:21  来源:igfitidea点击:

How do I determine the OS version at runtime in OS X or iOS (without using Gestalt)?

iosmacoscocoamacos-carbon

提问by Todd Ditchendorf

The Gestalt() function located in CarbonCore/OSUtils.hhas been deprecated as of OS X 10.8 Mountain Lion.

CarbonCore/OSUtils.h自 OS X 10.8 Mountain Lion起,位于 中的 Gestalt() 函数已被弃用。

I often use this function to test the version of the OS X operating system at runtime (see the toy example below).

我经常使用这个函数在运行时测试 OS X 操作系统的版本(参见下面的玩具示例)。

What other API could be used to check the OS X operating system version at runtime in a Cocoa application?

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

采纳答案by 0xced

On OS X 10.10 (and iOS 8.0), you can use [[NSProcessInfo processInfo] operatingSystemVersion]which returns a NSOperatingSystemVersionstruct, defined as

在 OS X 10.10(和 iOS 8.0)上,您可以使用[[NSProcessInfo processInfo] operatingSystemVersion]which 返回一个NSOperatingSystemVersion结构,定义为

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

There is also a method in NSProcessInfo that will do the comparison for you:

NSProcessInfo 中还有一个方法可以为您进行比较:

- (BOOL)isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion)version

Beware, although documented to be available in OS X 10.10 and later, both operatingSystemVersionand isOperatingSystemAtLeastVersion:exist on OS X 10.9 (probably 10.9.2) and work as expected. It means that you must not test if NSProcessInforesponds to these selectors to check if you are running on OS X 10.9 or 10.10.

当心,虽然记载了OS X 10.10及更高版本可用,都operatingSystemVersionisOperatingSystemAtLeastVersion:在OS X 10.9(存在可能10.9.2如预期)和工作。这意味着您不能测试是否NSProcessInfo响应这些选择器来检查您是在 OS X 10.9 还是 10.10 上运行。

On iOS, these methods are effectively only available since iOS 8.0.

在 iOS 上,这些方法仅在 iOS 8.0 之后有效。

回答by Variable Length Coder

On the command line:

在命令行上:

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

Programmatically:

以编程方式:

#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 version to OS X release:

达尔文版本到 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

A Sample to get and test versions :

获取和测试版本的示例:

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


}

Result on my machine macOs High Sierra 10.13.2

结果在我的机器上 macOs High Sierra 10.13.2

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

回答by iain

There is the NSAppKitVersionNumber value which you can use to check the various versions of AppKit, although they don't correspond exactly to OS versions

您可以使用 NSAppKitVersionNumber 值来检查 AppKit 的各种版本,尽管它们与操作系统版本并不完全对应

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

回答by DHL

There is a cocoa API. You can get an os X version string from the class NSProcessInfo.

有一个可可 API。你可以从类NSProcessInfo的OS X版本字符串。

The code to get the operating System Version String is below..

获取操作系统版本字符串的代码如下..

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

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

// ===>> Version 10.8.2 (Build 12C2034) result value

// ===>> 版本 10.8.2 (Build 12C2034) 结果值

It isn'tdeprecated.

没有被弃用。

回答by kainjow

There is also kCFCoreFoundationVersionNumber which can be used if you only need to check for a minimum version to support. This has the advantage that it works going back to 10.1 and can be done in C, C++, and Objective-C.

如果您只需要检查要支持的最低版本,也可以使用 kCFCoreFoundationVersionNumber。这样做的好处是它可以追溯到 10.1,并且可以在 C、C++ 和 Objective-C 中完成。

For example to check for 10.10 or greater:

例如,要检查是否有10.10或更高版本:

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

You will need to link with the CoreFoundation (or Foundation) framework.

您需要链接 CoreFoundation(或 Foundation)框架。

It also works in Swift in the exact same way. Here's another example:

它也以完全相同的方式在 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.")
}

回答by Vikas Bansal

You can easily get the major, minor, patch version of the Operating System using NSOperatingSystemVersion

您可以使用以下命令轻松获取操作系统的主要版本、次要版本和补丁版本 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];

回答by neowinston

Or, to put it more simply, here is the code:

或者,更简单地说,这是代码:

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

I hope this helps someone.

我希望这可以帮助别人。

回答by SentientAI

If you have an app that needs to run on 10.10 as well as prior versions, here's a solution:

如果您的应用程序需要在 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
}

Note that even 10.9 seems to respond to the operatingSystemVersion selector, so I think it just was a private API in 10.9 (but still works).

请注意,即使 10.9 似乎也响应了 operatingSystemVersion 选择器,所以我认为它只是 10.9 中的私有 API(但仍然有效)。

This works on all versions of OS X and doesn't rely on string parsing or file I/O.

这适用于所有版本的 OS X,并且不依赖于字符串解析或文件 I/O。

回答by Tibidabo

This is what I use:

这是我使用的:

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

It is recommended in AppKit Release Notes

AppKit 发行说明中推荐

Reading /System/Library/CoreServices/SystemVersion.plist is not possible if the app is sandboxed

如果应用程序被沙盒化,则无法读取 /System/Library/CoreServices/SystemVersion.plist

回答by Motti Shneor

This is actually a compilation of answers above, with some further guiding to the developer in need.

这实际上是上述答案的汇编,对有需要的开发人员有一些进一步的指导。

OS-X provides its version in runtime in several ways. Each way fits better to specific development scenario. I'll try to summarise them all, and hope that others will complete my answer if I forgot something.

OS-X 以多种方式在运行时提供其版本。每种方式都更适合特定的开发场景。我会尽量总结一下,如果我忘记了什么,希望其他人能完成我的回答。

First, the comprehensive list of ways to obtain the OS version.

首先,获取操作系统版本的方法的综合列表。

  1. The unamecommand-line tool and function provides the unix (darwin) version of the OS. Although this is not the marketing version of the OS, it is aligned with it uniquely, so you can deduce the OS-X marketing version from it.
  2. sysctl kern.osreleasecommand line (or sysctlbyname("kern.osrelease", str, &size, NULL, 0)function) will provide the same information as uname, marginally easier to parse.
  3. Gestalt(gestaltSystemVersionMajor)(with its "Minor" and BugFix" variants is the oldest (pre-Carbon!) API to get the marketing OS version, still supported by long deprecated. Available in C from the CoreServices framework, but not recommended.
  4. NSAppKitVersionNumberis a float constant of the AppKit framework, that will provide the OS-X Appkit version (aligned with the OS version), available to all applications which link against AppKit. It also provides a comprehensive enumeration of all possible versions (e.g. NSAppKitVersionNumber10_7_2)
  5. kCFCoreFoundationVersionNumberis a CoreFoundation framework float constant, identical to the Appkit counterpart, available to all apps linked against CoreFoundation, in both C, Obj-C and Swift. It, too provides a comprehensive enumeration over all OS X released versions (e.g. kCFCoreFoundationVersionNumber10_9)
  6. [[NSProcessInfo processInfo] operatingSystemVersionString];is a Cocoa API available in Obj-C to both OS-X and iOS applications.
  7. There is a resource .plist in /System/Library/CoreServices/SystemVersion.plistwhich among other things, contains the OS version in the "ProductVersion" key. NSProcessInfo reads its information from this file, but you can do this directly using your PList-reading API of choice.
  1. uname命令行工具和功能提供OS的UNIX(达尔文)版本。虽然这不是 OS 的营销版本,但它是独一无二的,因此您可以从中推断出 OS-X 营销版本。
  2. sysctl kern.osrelease命令行(或sysctlbyname("kern.osrelease", str, &size, NULL, 0)函数)将提供与 uname 相同的信息,稍微更容易解析。
  3. Gestalt(gestaltSystemVersionMajor)(其“ Minor”和BugFix“变体是获取营销操作系统版本的最古老的(碳之前!)API,但长期不推荐使用仍然支持。可从 CoreServices 框架在 C 中使用,但不推荐。
  4. NSAppKitVersionNumber是 AppKit 框架的浮点常量,它将提供 OS-X Appkit 版本(与 OS 版本一致),可用于所有与 AppKit 链接的应用程序。它还提供了所有可能版本的全面枚举(例如NSAppKitVersionNumber10_7_2
  5. kCFCoreFoundationVersionNumber是 CoreFoundation 框架浮点常量,与 Appkit 对应物相同,可用于所有与 CoreFoundation 链接的应用程序,包括 C、Obj-C 和 Swift。它也提供了对所有 OS X 发布版本的全面枚举(例如kCFCoreFoundationVersionNumber10_9
  6. [[NSProcessInfo processInfo] operatingSystemVersionString];是 OS-X 和 iOS 应用程序在 Obj-C 中可用的 Cocoa API。
  7. 有一个资源 .plist,/System/Library/CoreServices/SystemVersion.plist其中包含“ProductVersion”键中的操作系统版本。NSProcessInfo 从此文件中读取其信息,但您可以直接使用您选择的 PList 读取 API 来完成此操作。

For more details on each option - please consult the answers above. There's plenty of information there!

有关每个选项的更多详细信息 - 请参阅上面的答案。那里有很多信息!