我遇到了一个奇怪的问题,当试图测试一个符号的存在,是在一个较新版本的操作系统,我遵循苹果的指导方针使用弱链接符号,即。
通过显式地将外部常量或通知名称的地址(而不是符号的裸名称)与NULL或nil进行比较,检查其可用性。
为了重现这个问题,我在最新的Xcode 4.5.2上使用了最新的iOS 6 SDK,使用了默认的编译器(Apple LLVM compiler 4.1)。我弱链接了社交框架(仅在iOS 6+上可用)。我在iOS 5.1上运行了以下代码(部署目标低于6):
NSLog(@"%p", &SLServiceTypeFacebook);
if (&SLServiceTypeFacebook)
NSLog(@"Yes1");
if (&SLServiceTypeFacebook != NULL)
NSLog(@"Yes2");
输出为:
0x0
Yes1
Yes2
换句话说,我们可以在运行时验证表达式&SLServiceTypeFacebook
的计算结果是否为0。然而,测试此表达式的if
语句将其视为真。
***更新:***从this question中,我发现此变通方案在没有优化的情况下有效,但在优化的情况下无效:
typeof(&SLServiceTypeFacebook) foo = &SLServiceTypeFacebook;
if (foo)
NSLog(@"Yes3"); // does not get executed on -O0, but does on any optimization
***更新:***UIKit符号似乎不存在此问题。在iOS 4.3上运行以下程序:
NSLog(@"%p", &UIKeyboardDidChangeFrameNotification);
if (&SLServiceTypeFacebook)
NSLog(@"Yes1");
if (&SLServiceTypeFacebook != NULL)
NSLog(@"Yes2");
输出为:
0x0
我假设不同之处在于UIKit符号旁边有一个NS_AVAILABLE_IOS()
宏,所以编译器可以正确地处理它。对于Social框架符号,它没有NS_AVAILABLE_IOS()
宏,因为整个Social框架本身只有在iOS 6之后才可用(即,该符号自框架版本起可用,所以我猜不需要此宏?);但是编译器不能正确地处理该符号。
2条答案
按热度按时间ncgqoxb01#
是否确定不检查SLRequest类是否存在,而不检查此常量?
在任何情况下,问题是编译器优化了测试(它将此解释为测试一个在编译时为真的常量表达式)。您可以通过将此地址读入一个本地volatile变量来避免此问题。或者您可以在运行时动态搜索符号。
但我会考虑只检查SLRequest类。
这里至少有这三种选择:
在iOS5.1与iOS6中,所有这些都应该像您预期的那样工作。
ergxz8rk2#
如果你能得到类,就用NSClassFromString检查一下。. objC是所有的类:D