8

我在一些项目中看到过:

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

但我现在找不到它......
例如,如果应用程序在 10.8 上运行,则应用程序执行 1 件事,否则应用程序执行其他操作。用什么代码检查它是否在 10.8 上运行?
谢谢。

4

7 回答 7

24

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

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

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

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

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

回顾一下:

  1. 检测单个类和方法,它们应该涵盖 99.44% 的案例。
  2. 使用NSAppKitVersionNumberandNSAppKitVersionNumber10_7来涵盖类或方法检测对您不利的情况。
  3. 前两点涵盖了所有正常情况。你不应该再往前走了。但是,如果您必须有基于人性化版本的行为,请查看下面的 abarnert 的答案。这是获取它们的最明智的方法。
  4. 不要使用operatingSystemVersionString,它被明确列为不安全的解析。

参考资料/更多信息:

  • SDK 兼容性指南“如果您希望您的应用程序针对特定版本或多个版本的 iOS 或 Mac OS X,请阅读此文档。”
于 2012-06-15T18:13:14.097 回答
12

一个快速的方法是:

if ( NSAppKitVersionNumber >= NSAppKitVersionNumber10_7 ) {

    // Do stuff for Lion or later
}

更多在这里

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

如果您愿意,头文件提供了一些令人惊讶的有趣阅读材料。

于 2012-06-15T19:21:18.697 回答
4

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

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

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

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

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

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

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

于 2012-06-15T23:31:47.477 回答
2

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

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

于 2012-06-15T18:06:18.237 回答
2

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

检查特定类是否可用

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

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

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

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

于 2012-10-19T08:03:00.863 回答
0

这是我如何做的代码。我喜欢这种方式,主要是因为我不必 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];
}

享受!

于 2012-09-06T02:13:05.600 回答
-4

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

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

NSLog(version);

输出:

截屏


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

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

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

NSLog(@"%@", justVersion);

结果:

截屏

并用于检查:

if ([justVersion isEqualToString:@"10.7"]) {
    code...
}
else {
    ...
}
于 2012-06-15T17:55:03.650 回答