xcode iOS中弱链接符号的测试未按预期运行

qlzsbp2j  于 2023-01-06  发布在  iOS
关注(0)|答案(2)|浏览(120)

我遇到了一个奇怪的问题,当试图测试一个符号的存在,是在一个较新版本的操作系统,我遵循苹果的指导方针使用弱链接符号,即。
通过显式地将外部常量或通知名称的地址(而不是符号的裸名称)与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之后才可用(即,该符号自框架版本起可用,所以我猜不需要此宏?);但是编译器不能正确地处理该符号。

ncgqoxb0

ncgqoxb01#

是否确定不检查SLRequest类是否存在,而不检查此常量?
在任何情况下,问题是编译器优化了测试(它将此解释为测试一个在编译时为真的常量表达式)。您可以通过将此地址读入一个本地volatile变量来避免此问题。或者您可以在运行时动态搜索符号。
但我会考虑只检查SLRequest类。
这里至少有这三种选择:

#include <dlfcn.h>

NSString* const * volatile check = &SLServiceTypeFacebook;
if (check != NULL)
    NSLog(@"SLServiceTypeFacebook is defined");

// Another approach would be to call dlsym() at runtime 
// to search for this symbol:
if (dlsym(RTLD_DEFAULT, "SLServiceTypeFacebook"))
    NSLog(@"SLServiceTypeFacebook found via dlsym");

// But if you really just wanted to know is if SLRequest
// is available, you should really just do this:
if ([SLRequest class])
    NSLog(@"SLRequest class is available");

在iOS5.1与iOS6中,所有这些都应该像您预期的那样工作。

ergxz8rk

ergxz8rk2#

如果你能得到类,就用NSClassFromString检查一下。. objC是所有的类:D

相关问题