Objective c 将消息传递给零的开销/风险

Objective c 将消息传递给零的开销/风险,objective-c,null,Objective C,Null,我想知道,依赖于将消息传递给nil对象在目标C中没有任何作用这一事实是否存在任何风险 在我的代码中,我有很多对UIKit和其他对象的弱引用,这些引用可以随时为零。由于我来自C++和引用NULL的语言是最快的方法如何崩溃程序,我总是倾向于谨慎和编写防御CODELIKE这一点: if (view) [view removeFromSuperview]; 在向视图传递消息之前,是否有必要检查视图是否为nil?我知道在这种情况下(从superview中删除子视图是安全的),但是在任何情况下这都可

我想知道,依赖于将消息传递给nil对象在目标C中没有任何作用这一事实是否存在任何风险

在我的代码中,我有很多对UIKit和其他对象的弱引用,这些引用可以随时为零。由于我来自C++和引用NULL的语言是最快的方法如何崩溃程序,我总是倾向于谨慎和编写防御CODELIKE这一点:

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肯定没有初始化(在发行版中运行它,您会看到).重复检查。结构未初始化。