如何针对特定的iPhone版本进行目标定向?

36

我有一些代码,希望只在最新的 iPhone SDK (3.0) 上执行,但是我似乎无法找到能够仅针对 3.0 并忽略 2.2.1 等版本的方法。虽然有一个 ifdef 语句,但它似乎只覆盖整个 iPhone:

#if TARGET_OS_IPHONE

非常感谢任何帮助。

8个回答

88
你可以使用这个 #define 来更改构建每个SDK的内容...
#if __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_2_2
// iPhone 3.0 code here
#endif

并在运行时进行以下操作以运行 3.0 及以上版本的代码:

float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 3.0)
    {
    // iPhone 3.0 code here
    }

10
需要注意的一件事是,为模拟器和设备编译可能会导致这些宏的意外变化。当使用模拟器SDK 2.2.1进行编译时,我得到了__IPHONE_OS_VERSION_MIN_REQUIRED = 20000。然而,当为设备编译时,我得到了__IPHONE_OS_VERSION_MIN_REQUIRED = 20201,这破坏了您上面定义的条件。我目前正在使用纯粹的“#ifdef __IPHONE_3_0”来隔离仅在3.0或更高版本中有效的代码。这有效,因为该宏直到3.0 SDK才被定义。 - n8gray
5
注意运行时代码。调用floatValue方法,即使实际版本为3.2.2,也只会得到3.20000。请谨慎处理。 - Joseph Tura
当我使用Xcode 4在iPhone(4.3.1)上构建和运行时,为什么会出现__IPHONE_OS_VERSION_MIN_REQUIRED = 30200? - ma11hew28
3
你的回答中的运行时代码是完全错误的。浮点数和字符串具有不同的排序方式:3.10 < 3.2,但是"3.10" > "3.2"。此外,版本字符串可能有超过两个部分(例如,5.0.1,在许多应用程序中用于从iCloud备份中排除文件)。进行版本检查的正确方法是使用 [systemVersion compare:version options:NSNumericSearch] - yakovlev
版本号不是浮点数,也不是十进制数。版本号是由点字符分隔的整数。 - David Pisoni
为什么不用 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0 - Ky -

19

我会谨慎处理返回的floatValue结果:

[[[UIDevice currentDevice] systemVersion] floatValue]

与所有浮点数一样,它可能不会完全符合您的预期。当我在我的系统上运行上述代码时,困惑于我的条件语句为什么没有执行,我注意到返回的值是:

3.20000005

推荐在此处查找解决方案: 如何检查iOS版本?

摘录:

NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"3.1.3" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 3.1.3
} else {
    // OS version < 3.1.3
}

3.2.00..005版本的doubleValue问题是否仍然存在? - Ky -
@BenC.R.Leggiero 应该是这样的。无论你使用多少精度,都不可能在二进制中准确表示3.2。 - Brennan Vincent
@BrennanVincent 我想你是指IEEE浮点数,因为使用NSDecimalNumber来表示是微不足道的。 - Ky -
@BenLeggiero 我说的是二进制。NSDecimalNumber不是“二进制”,它是二进制编码的十进制。我的陈述是关于数学,而不是计算机技术。double是二进制的,因此在数学上不可能精确表示3.2。 - Brennan Vincent

6

更新:在使用Xcode 4构建和运行iPhone(4.3.1)时,此方法似乎不再适用于我。同时,我得到了__IPHONE_OS_VERSION_MIN_REQUIRED = 30200

《iPhone开发者手册》中提到您也可以这样做:

#ifdef _USE_OS_4_OR_LATER
    // code to compile for 4.0 or later
#else
    // code to compile for pre-4.0
#endif

看起来对我来说也有效。:)


我找不到在Foundation中定义的地方。它在哪里? - Ky -

4

我很确定你也可以这样做:

#ifdef __IPHONE_3_0
// 3.0 code here
#endif

请注意,前往那里的代码是3.0+,而不仅仅是3.0。 - Ky -

0

这在Xcode的构建选项中。左上角的下拉菜单显示类似“myapp - 3.0 | Debug”的内容。 选择您想要的构建,完成后就可以了。


该方法的问题在于我希望我的应用程序也能在2.2.1上运行,并且只有这一行代码在3.0上运行。你的方法意味着我必须放弃对2.2x的支持。 - Oliver
我现在明白你的意思了,很棘手,但你也许可以进行精确定位的检查。比如,在头文件中检查一个定义。 - Robert Gould

0
使用从this answer中添加OTHER_CFLAGS =“-g3 -save-temps -dD”的技巧,我发现在针对2.2.1的项目中定义__IPHONE_OS_VERSION_MIN_REQUIRED 20000。也许这会起作用?

0

我相当确定OP的评论总结了一切。你不能这样做。因为编译时指令无法做出运行时决策。在Xcode中,如果你的目标是3.0,它将无法在2.2.1手机上运行。如果你的目标是2.2.1,它将无法编译,因为你有3.0特定的代码。

唯一真正的解决方案是你的应用程序有两个版本,一个编译为3.0,另一个编译为2.2.1。


  1. 实际上,OP并没有排除编译时检查。
  2. 你所提供的规则有例外情况。例如,MPMoviePlayerController在3.0和3.2上都存在,但在3.2(和4.0)上的工作方式不同 - 为了在两个平台上正确支持它,我发现使用运行时操作系统版本检查非常方便。在我的特殊情况下,省略此检查仍将在两个平台上导致正确的构建,但在3.2以下的任何版本上都会崩溃。
- Till

-2

嗯,我有两句话要说:

你可以使用最新的版本(比如3.0)构建你的应用程序,这样你就可以利用所有新的和酷炫的API,并将部署目标指定为你想要支持的最早期版本,这样那些没有花时间升级设备的人仍然可以运行你的应用程序。在这种情况下,如上所示,你需要检查SDK的最早期版本,并提供替代功能,使你的应用程序向后兼容。

此致, Hardik


这如何帮助只在iOS 3或更高版本上运行一部分代码? - Ky -

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接