Iphone 在iOS中测试弱链接符号无法按预期工作

Iphone 在iOS中测试弱链接符号无法按预期工作,iphone,objective-c,ios,xcode,weak-linking,Iphone,Objective C,Ios,Xcode,Weak Linking,我在尝试测试新版本操作系统中引入的符号是否存在时遇到了一个奇怪的问题。我继续使用弱链接符号,即 检查外部(外部)常量或 通过显式比较其地址而不是 符号的裸名称为NULL或nil 为了重现这个问题,我在最新的Xcode 4.5.2上使用最新的iOS 6 SDK,使用默认编译器(Apple LLVM编译器4.1)。我弱链接了社交框架(仅在iOS 6+上可用)。我在iOS 5.1上运行此代码(部署目标低于6): 输出为: 0x0 Yes1 Yes2 0x0 换句话说,我们可以在运行时验证表达式&S

我在尝试测试新版本操作系统中引入的符号是否存在时遇到了一个奇怪的问题。我继续使用弱链接符号,即

检查外部(外部)常量或 通过显式比较其地址而不是 符号的裸名称为NULL或nil

为了重现这个问题,我在最新的Xcode 4.5.2上使用最新的iOS 6 SDK,使用默认编译器(Apple LLVM编译器4.1)。我弱链接了社交框架(仅在iOS 6+上可用)。我在iOS 5.1上运行此代码(部署目标低于6):

输出为:

0x0
Yes1
Yes2
0x0
换句话说,我们可以在运行时验证表达式
&SLServiceTypeFacebook
的计算值是否为0。然而,
if
语句对该表达式进行测试,并将其视为是真的


更新: 从中,我发现此解决方案不需要优化,但不需要优化:

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
Yes1
Yes2
0x0

我假设区别在于UIKit符号旁边有一个
NS\u AVAILABLE\u IOS()
宏,因此编译器可以正确地处理它。在社交框架符号的情况下,它没有
NS\u AVAILABLE\u IOS()
宏,因为整个社交框架本身仅在IOS 6之后可用(即,该符号自框架版本起可用,因此我猜不需要该宏);但是编译器不能正确处理符号。

您确定不想检查SLRequest类是否存在,而不是检查该常量吗

在任何情况下,问题在于编译器正在优化测试(它将此解释为测试在编译时为真的常量表达式)。您可以通过将此地址读入本地volatile变量来规避此问题。或者,您可以在运行时动态搜索符号

<>但是我会考虑只检查SLRev1类。

以下至少有三个选项:

#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");
#包括
NSString*const*volatile check=&SLServiceTypeFacebook;
如果(检查!=NULL)
NSLog(@“定义了SLServiceTypeFacebook”);
//另一种方法是在运行时调用dlsym()
//要搜索此符号,请执行以下操作:
如果(dlsym(RTLD_默认值,“SLServiceTypeFacebook”))
NSLog(@“通过dlsym找到的SLServiceTypeFacebook”);
//但如果你真的想知道的话是不是
//如果可用,您应该只执行以下操作:
如果([SLRequest类])
NSLog(@“SLRequest类可用”);
其中任何一个都应该像您在iOS5.1和iOS6中所期望的那样工作


希望这能有所帮助。

如果你能得到这些类,请与NSClassFromString联系。。objC无论如何都是类:D

第一行不应该是
NSLog(@“%p”,SLServiceTypeFacebook)
其中
SLServiceTypeFacebook
是指针吗?@robotcat:不,不可用的弱链接符号的地址是0,尝试访问该符号将导致一个segdault.OK-最后一想(然后我就没主意了)-关于
NSLog(@“%x”和&SLServiceTypeFacebook)的情况如何
?@Robotcat如果只是以不同的格式打印,则传递的值将是相同的。@JustSid:它们应返回不同的值(注意第一条注释中的no
&
与第二条注释中的
&
)。无论如何,这只是一个想法。1)我没有启用任何优化,2)这是测试符号可用性的公认方法,用于在Xcode中工作(参见示例),您可以检查编译器输出以验证是否正在编译此条件,即使在调试配置文件中也是如此。如果你觉得这是一个叮当作响的bug,那么radr当然是这个地方。否则,以下是适用于装运代码的选项。我认为,类本身的测试更好。@FirozeLafeer你确定这是故意的优化,还是仅仅是猜测?我对此感到困惑,因为在修复之前,如何在编译时知道该值?我正在试图弄清楚这是否是(或曾经是)一个bug或其他正在发生的事情,以及它是否仍然是一个值得关注的问题?此外,是否有一个很好的分析,以明确显示发生了什么?1)客观C不是所有的类。2) 我在这里检查变量的可用性,而不是类,所以这完全不相关。3) 您甚至不需要执行
NSClassFromString
来检查类的可用性。只需检查
[class类]
,或直接向其传递任何其他消息
[class someMessage]
即可。如果该类不可用,则该类对象将为
nil
。我完全知道它不是所有的类:P因此是->:D |但是很多都是围绕类进行的,在检查某个类或方法时,检查符号可能是不必要的。另一个答案还建议检查类btw!>|到3--安全吗?您正在使用类的符号。我看到的文档都使用字符串来避免未引用的符号?如果是:酷