Objective c 将消息传递给零的开销/风险
我想知道,依赖于将消息传递给nil对象在目标C中没有任何作用这一事实是否存在任何风险 在我的代码中,我有很多对UIKit和其他对象的弱引用,这些引用可以随时为零。由于我来自C++和引用NULL的语言是最快的方法如何崩溃程序,我总是倾向于谨慎和编写防御CODELIKE这一点:Objective c 将消息传递给零的开销/风险,objective-c,null,Objective C,Null,我想知道,依赖于将消息传递给nil对象在目标C中没有任何作用这一事实是否存在任何风险 在我的代码中,我有很多对UIKit和其他对象的弱引用,这些引用可以随时为零。由于我来自C++和引用NULL的语言是最快的方法如何崩溃程序,我总是倾向于谨慎和编写防御CODELIKE这一点: if (view) [view removeFromSuperview]; 在向视图传递消息之前,是否有必要检查视图是否为nil?我知道在这种情况下(从superview中删除子视图是安全的),但是在任何情况下这都可
if (view)
[view removeFromSuperview];
在向视图传递消息之前,是否有必要检查视图是否为nil?我知道在这种情况下(从superview中删除子视图是安全的),但是在任何情况下这都可能是一个问题吗
性能影响如何?向nil传递消息实际上是免费的,并且实际上什么都不做吗?如果我说在一个循环中做上千次呢?根据苹果的文档 如果没有其他值可以使用,nil值是初始化对象指针的最安全的方法,因为在Objective-C中,向nil发送消息是完全可以接受的。如果您确实向nil发送了一条消息,那么显然什么也没有发生
这意味着您可以将想要的内容发送到nil对象,而Objective-C中的方法调用将通过将它们转换为对
objc_msgSend()
的调用来处理,该调用首先检查接收方是否为nil
,然后将其转换为对特殊“nil”对象的方法调用。(见博客帖子:)。方法调用被设计为对所有类型返回0。见:
注意:如果您希望从发送到nil
的消息返回值,则对于对象返回类型,返回值将为nil
,对于数值类型,返回值将为0
,对于BOOL
类型,返回值将为NO
。返回的结构的所有成员都已初始化为零
所以它总是安全的。除非您支持遗留系统
对于遗留编码器。。。
过去的情况是,objc_msgSend()
在标量函数返回的常规寄存器中只返回0。PowerPC上的ABI指定r3
将用于整数和指针返回,如果结构打包到寄存器中,有时用于结构的第一个字段。然而,不同的寄存器用于浮点数,这些寄存器不会被初始化,结构也不会总是被初始化
这是一个极为罕见的问题,但无论如何都已得到解决。将消息传递给
nil
是非常正常的,在Objective-C中也是如此。您通常不应该对此进行防护。但是,请记住,将nil
传递给某些方法(例如addObject:
)将导致崩溃,因此您确实需要考虑变量何时可以是nil
objc\u msgSend
经过高度优化,可处理消息传递nil。objc\u msgSend
中的第一条汇编指令是对nil
的测试,并立即返回
编辑:
请参阅Dietrich Epp关于如何处理非对象返回的回答。他提出了一个很好的观点,那就是在这种情况下你确实需要小心。苹果的运行人员格雷格·帕克(Greg Parker)在这里写了一篇关于这个主题的博文: 我认为这比苹果链接更确切,因为它也是过时的。 消息nil将返回0,用于任何高达64位的整数、高达长双精度的浮点、指针、结构或_复数。请注意,直接调用
objc\u msgSend\u stret
并非在所有情况下都具有相同的行为
由于运行时需要查找类以正确地分派消息,因此我认为它很早就发现实例为零。关于返回结构的极好警告。注意,在ARC中,编译器将为您处理所有这些棘手的情况,包括清空结构。这似乎是正确的,但我担心没有引用支持这一点,或者这可能是ABI的一个怪癖。ARC只承诺初始化对象(请参阅转换为ARC发行版说明:堆栈变量是用nil初始化的)。您可能会认为它在用于Clang的ObjC ARC文档中,但我在那里找不到它。但有可能结构被视为对象(因为它们看起来几乎相同)。堆栈int肯定没有初始化(在发行版中运行它,您会看到).重复检查。结构未初始化。