xcode 如何知道应用程序在什么 Mac OS 上运行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11055146/
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-09-15 00:37:13  来源:igfitidea点击:

How to know what Mac OS the app is running on?

objective-cxcodemacoscocoaosx-mountain-lion

提问by Pedro Vieira

I've seen in some projects something like:

我在一些项目中看到过这样的事情:

#if .....
    code...
#endif

but i can't find it now...
Let's say, for example, if the app is running on 10.8 the app does 1 thing, if not the app does other thing. Whats to code to check if it's running on 10.8?
Thanks.

但我现在找不到它...
假设,例如,如果该应用程序在 10.8 上运行,则该应用程序会做 1 件事,否则该应用程序会做其他事情。什么代码来检查它是否在 10.8 上运行?
谢谢。

回答by Steven Fisher

You're probably asking the wrong question. Except in very rare cases, you should not care what system version the user is running. Instead, you should be checking if the specific thing you're interested in is available.

你可能问错了问题。除了在极少数情况下,您不应该关心用户正在运行的系统版本。相反,您应该检查您感兴趣的特定事物是否可用。

For instance, if Apple introduces a MagicHologram class in Mac OS X 10.9 that you want to use, you don't check if the user is running Mac OS X 10.9. Instead, you check if the MagicHologram class is available. If it is, you can use it. If not, it's not available. It doesn't even matter why. Maybe they're running 10.8. But maybe it's five years later, and Apple's decided to drop the MagicHologram class entirely.

例如,如果 Apple 在 Mac OS X 10.9 中引入了一个您想要使用的 MagicHologram 类,您就不会检查用户是否正在运行 Mac OS X 10.9。相反,您检查 MagicHologram 类是否可用。如果是,您可以使用它。如果没有,则不可用。甚至不重要为什么。也许他们正在运行 10.8。但也许是五年后,Apple 决定完全放弃 MagicHologram 类。

(Also, keep in mind that you'd need to weak link to HologramKit, the library that provides the MagicHologram class.)

(另外,请记住,您需要弱链接到 HologramKit,即提供 MagicHologram 类的库。)

Likewise, if they introduce a new method to NSString, instead of checking the OS version you'd check if NSString knows about the new method.

同样,如果他们向 NSString 引入了一个新方法,您将检查 NSString 是否知道新方法,而不是检查操作系统版本。

That said, NSApplication.h includes an external constant called NSAppKitVersionNumber. You can compare this to constants like NSAppKitVersionNumber10_7which (it should be noted) are numbers like 1138, not 10.7. There's only a few places this is appropriate, mostly where classes were private and undocumented but got major changes before being documented and becoming a part of the public parts of the SDK. Also, it might be helpful if you want to avoid a specific bug that's been fixed since.

也就是说, NSApplication.h 包含一个名为NSAppKitVersionNumber. 您可以将其与NSAppKitVersionNumber10_7诸如 1138 之类的数字而非 10.7 之类的常量进行比较(应注意)。只有少数地方是合适的,主要是类是私有的和未记录的,但在被记录并成为 SDK 公共部分的一部分之前发生了重大变化。此外,如果您想避免此后已修复的特定错误,这可能会有所帮助。

To recap:

回顾一下:

  1. Detect individual classes and methods, which should cover 99.44% of your cases.
  2. Use NSAppKitVersionNumberand NSAppKitVersionNumber10_7to cover those cases where class or method detection would lie to you.
  3. Those first two points cover all normalcases. You should go no further. But if you must have behaviour based on humane version, look at abarnert's answer below. It's the sanest way to get them.
  4. Don't use operatingSystemVersionString, which is specifically listed as not safe for parsing.
  1. 检测单个类和方法,它们应该涵盖 99.44% 的案例。
  2. 使用NSAppKitVersionNumberNSAppKitVersionNumber10_7来涵盖那些类或方法检测会骗你的情况。
  3. 前两点涵盖了所有正常情况。你不应该再进一步了。但是,如果您必须具有基于人道版本的行为,请查看下面 abarnert 的回答。这是获得它们的最明智的方法。
  4. 不要使用operatingSystemVersionString,它被明确列为不安全的解析。

References/more information:

参考资料/更多信息:

  • SDK Compatibility Guide"Read this document if you want your application to target a specific version or multiple versions of iOS or Mac OS X."
    • Using SDK-Based DevelopmentDescribes how to use weakly linked classes, methods, and functions to support running on multiple versions of an operating system.
  • SDK 兼容性指南“如果您希望您的应用程序面向特定版本或多个版本的 iOS 或 Mac OS X,请阅读此文档。”

回答by Monolo

A quick way to do it is:

一个快速的方法是:

if ( NSAppKitVersionNumber >= NSAppKitVersionNumber10_7 ) {

    // Do stuff for Lion or later
}

More here.

更多在这里

You can see all the constants available in NSApplication.h, which you can get to by using Open Quickly... (Cmd-Shift O) in Xcode.

您可以在 NSApplication.h 中看到所有可用的常量,您可以通过在 Xcode 中使用 Open Quickly... (Cmd-Shift O) 来获取这些常量。

The header files provide for some surprisingly interesting reading material, if you are so inclined.

如果您愿意,头文件提供了一些非常有趣的阅读材料。

回答by abarnert

As others have said above (and I'd pick Steven Fisher's answer), you usually do not actually want to get the version number.

正如上面其他人所说(我会选择 Steven Fisher 的答案),您通常实际上并不想获得版本号。

And if you only need to do comparisons against a major OS X version up to the version of the current SDK you're using, NSAppKitVersionNumber (as in Monolo's answer) is the right way to do it.

如果您只需要与主要的 OS X 版本进行比较,直到您使用的当前 SDK 的版本,NSAppKitVersionNumber(如 Monolo 的答案)是正确的方法。

If you actually do need to get the version number for some reason (e.g., for recording analytics about your users, so you can decide when to stop supporting 10.6.0-10.6.5), here's how to do it:

如果您出于某种原因确实需要获取版本号(例如,为了记录有关您的用户的分析,以便您可以决定何时停止支持 10.6.0-10.6.5),请按以下步骤操作:

#import <CoreServices/CoreServices.h>
SInt32 majorVersion, minorVersion, bugFixVersion;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
Gestalt(gestaltSystemVersionMinor, &minorVersion);
Gestalt(gestaltSystemVersionBugFix, &bugFixVersion);  

For 10.7.3, this gives majorVersion = 10, minorVersion = 7, bugFixVersion = 3.

对于 10.7.3,这给出了majorVersion = 10,minorVersion = 7,bugFixVersion = 3。

The 10.7 documentation removed the paragraph that directly suggested Gestalt as the way to get OS version, but it's still not deprecated or legacy, and there's no other suggestions. In fact, every other way to get this information (parsing -[NSProcessInfo operatingSystemVersionString], calling sysctlbyname on "kern.osrelease" and converting Darwin kernel version to OS X version, etc.) is explicitly counter-indicated somewhere. So, this is the way to do it, if you really want to.

10.7 文档删除了直接建议格式塔作为获取操作系统版本方式的段落,但它仍然没有被弃用或遗留,并且没有其他建议。实际上,获取此信息的所有其他方式(解析 -[NSProcessInfo operatingSystemVersionString]、在“kern.osrelease”上调用 sysctlbyname 并将 Darwin 内核版本转换为 OS X 版本等)都在某处明确地反指示。所以,如果你真的想要,这就是这样做的方法。

Just keep in mind that, as the release notes for System 6.0.4 said back in 1989, this new API may not be permanent and could be removed in a future version of the OS.

请记住,正如 1989 年 System 6.0.4 的发行说明所说,这个新 API 可能不是永久性的,可能会在未来版本的操作系统中删除。

回答by abarnert

You can get the current release from the uname -rcommand (that's actually the kernel release, though it's easy to map onto Mac OS X versions), from the sw_verscommand which gives you the release name, version and build identifier, or from the Gestalt()function (on current versions of Mac OS X, anyway). The safest way is probably to read the output of sw_verswhich is in a stable format that's easy to parse.

您可以从uname -r命令(这实际上是内核版本,尽管很容易映射到 Mac OS X 版本)、从sw_vers为您提供版本名称、版本和构建标识符的命令或从Gestalt()函数(在当前无论如何,Mac OS X 版本)。最安全的方法可能是读取sw_vers易于解析的稳定格式的输出。

Notice that you probably don't want to know what version of the OS you're on, though. What you probably want to do is to test whether a particular feature is available. You can do this by weak-linking frameworks, by weak class references, or by inspecting whether a class responds to selectors appropriate to the feature you're interested in.

请注意,您可能不想知道您使用的是哪个版本的操作系统。您可能想要做的是测试特定功能是否可用。您可以通过弱链接框架、弱类引用或检查类是否响应适合您感兴趣的功能的选择器来实现这一点。

回答by codingFriend1

As Steven Fisher said, you should not check for the system version but for the availability of the class or method you want to use.

正如 Steven Fisher 所说,您不应该检查系统版本,而应该检查您要使用的类或方法的可用性。

The check if a specific class is available use

检查特定类是否可用

if ([NSHologram class]) {
   // Create an instance of the class and use it.
} else {
   // The Hologram class is not available.
}

To check if a specific method is available use

要检查特定方法是否可用,请使用

NSString* hologramText = @"Hologram";
if ([hologramText respondsToSelector:@selector(convertHologram)]) {
    [hologramText convertHologram];
}

Yet for the method checking, the method must be available on the system where you build your app, or else you will get a compile error.

然而对于方法检查,该方法必须在您构建应用程序的系统上可用,否则您将收到编译错误。

回答by Arvin

Here is code for how I do it. I love it this way, mainly because I don't have to A) Rely on an NSTask or B) Rely on any File I/O that many processes have access to.

这是我如何做的代码。我喜欢这种方式,主要是因为我不必 A) 依赖 NSTask 或 B) 依赖许多进程可以访问的任何文件 I/O。

static NSString* const kVarSysInfoVersionFormat  = @"%@.%@.%@ (%@)";
static NSString* const kVarSysInfoKeyOSVersion = @"kern.osrelease";
static NSString* const kVarSysInfoKeyOSBuild   = @"kern.osversion";

- (NSString *) _strControlEntry:(NSString *)ctlKey {

    size_t size = 0;
    if ( sysctlbyname([ctlKey UTF8String], NULL, &size, NULL, 0) == -1 ) return nil;

    char *machine = calloc( 1, size );

    sysctlbyname([ctlKey UTF8String], machine, &size, NULL, 0);
    NSString *ctlValue = [NSString stringWithCString:machine encoding:[NSString defaultCStringEncoding]];

    free(machine); return ctlValue;
}

- (NSString *) getOSVersionInfo {

    NSString *darwinVer = [self _strControlEntry:kVarSysInfoKeyOSVersion];
    NSString *buildNo = [self _strControlEntry:kVarSysInfoKeyOSBuild];
    if ( !darwinVer || !buildNo ) return nil;

    NSString *majorVer = @"10", *minorVer = @"x", *bugFix = @"x";
    NSArray *darwinChunks = [darwinVer componentsSeparatedByCharactersInSet:[NSCharacterSet punctuationCharacterSet]];

    if ( [darwinChunks count] > 0 ) {

        NSInteger firstChunk = [(NSString *)[darwinChunks objectAtIndex:0] integerValue];
        minorVer = [NSString stringWithFormat:@"%ld", (firstChunk - 4)];
        bugFix = [darwinChunks objectAtIndex:1];

    } return [NSString stringWithFormat:kVarSysInfoVersionFormat, majorVer, minorVer, bugFix, buildNo];
}

Enjoy!

享受!

回答by Justin Boo

You can get OS version like this:

您可以获得这样的操作系统版本:

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

NSLog(version);

Output:

输出:

screenshot

截屏



我看到你只想得到版本。可以这样做:

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

NSRange range = NSMakeRange(8, 4);
NSString *justVersion = [version substringWithRange: range];

NSLog(@"%@", justVersion);

Result:

结果:

screenshot

截屏

And for checking:

并用于检查:

if ([justVersion isEqualToString:@"10.7"]) {
    code...
}
else {
    ...
}