Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在进行选择器调用之前显式检查nil有什么好处吗?_Ios_Objective C_Performance - Fatal编程技术网

Ios 在进行选择器调用之前显式检查nil有什么好处吗?

Ios 在进行选择器调用之前显式检查nil有什么好处吗?,ios,objective-c,performance,Ios,Objective C,Performance,我见过这样的代码: if(myObject&&[myObject mySelector])… 我听说这可以防止不必要的选择器查找和方法调用,从而将选择器消息发送到运行时发现为零的对象指针 然而,我认为objective-C的一个核心原则是,对nil对象的所有选择器调用都返回nil,因此我希望它在编译器方面得到了很好的优化 有人知道这种模式在性能方面是否真的有任何优势吗?除了给未来的开发人员一个提示,即nil在那里是可以接受的,它没有任何用途。我希望代码在任何选择器查找发生之前退出 有人知道这种模

我见过这样的代码:

if(myObject&&[myObject mySelector])…

我听说这可以防止不必要的选择器查找和方法调用,从而将选择器消息发送到运行时发现为零的对象指针

然而,我认为objective-C的一个核心原则是,对nil对象的所有选择器调用都返回nil,因此我希望它在编译器方面得到了很好的优化


有人知道这种模式在性能方面是否真的有任何优势吗?

除了给未来的开发人员一个提示,即
nil
在那里是可以接受的,它没有任何用途。我希望代码在任何选择器查找发生之前退出

有人知道这种模式在性能方面是否真的有任何优势吗

标准答案:在所有可能的情况下,性能无法区分

真正的答案:一个人需要更多的指令和跳跃,就会有一些性能差异,如果你在编写重要的代码类型,你就会知道这是否是一个重要的差异,否则你就不会编写这种代码了

我只是好奇回答:好奇是好的,保持好奇!使用标准Xcode模板编写一个非常简单的程序。首先使用方法
mySelector
添加一个类
MyObject
,返回类型
long
,该方法将
1L
返回到
AppDelegate.m
文件中

现在在
AppDelegate
实现中编写一个小测试方法,类似于:

- (int) test:(MyObject *)myObject
{
   if (myObject && [myObject mySelector])
      return 42;
   else
      return 24;
}
然后在
applicationdFinishLaunching
中添加一些代码以调用
test
并通过
nil
MyObject的一个实例
NSLog
返回值

运行它

现在转到**产品->执行操作->组装“AppDelegate.m”。这将生成生成的汇编语言列表。在这个列表的底部是一个菜单,允许您选择构建的类型,从而选择汇编代码的优化程度;“运行”几乎没有优化,并且是在开发和调试时使用的,“归档”显示在构建最终应用程序时生成的优化代码

如果您查看程序集(如果您不知道x86代码,请不要担心指令名表明了它们的含义),您将看到
nil
的初始测试是两条指令:compare&jump(为else分支编写代码)。之后是消息调用的代码:将参数(即
myObject
和选择器)加载到寄存器中,调用
objc\u msgSend
,然后进行比较和跳转以测试其返回值

你看不到objc\u msgSend做了什么,因为那不是你的代码。要发现这一点:在
if
上放置一个断点,然后运行。当它停止时,打开助手编辑器并将其设置为显示反汇编–现在,您将在左面板中显示Objective-C代码,在右面板中显示匹配的组装代码

这两个面板下面是调试控件,如果将鼠标悬停在它们上面,将弹出工具提示,说明每个面板的作用。找到“单步执行”并按住控制键并单击,因为工具提示显示这是“单步执行指令”,并将一次单步执行一条指令,而不是Objective-C源代码行。重复control+单击,直到右侧面板显示您已进入了
objc\u msgSend

现在查看
objc\u msgSend
程序集,您将看到它以
nil
的比较和跳转开始,如果您遵循跳转的方向,则有清除四个寄存器然后返回的说明

因此,如果在
if
中没有初始
nil
测试,代码将加载两个参数寄存器,跳转到
objc\u msgSend
,比较、测试、清除4个寄存器,然后返回到代码,然后对返回值进行比较和跳转

这显然是
nil
案例中的更多说明

但是非nil案例需要在if中进行比较和跳转,这是不必要的。。。因此,“哪个性能更好”取决于
nil
和非
nil
值的统计分布,这取决于代码。。。请记住,现代机器每秒执行数百万条指令,并且具有分支谓词和缓存等功能,即使在代码跳跃时也能保持快速执行

希望到目前为止,您的好奇心已经让您理解了上面的“标准答案”,并为您提供了代码类型和应用程序领域的提示,在这些领域中,它可能会在性能方面产生实际的影响

因此,如果您认为初始测试澄清了代码的目的,那么就包含它,否则不要包含。您的代码可能运行得更快或更慢,但您不会注意到这两种情况,除非计算纳秒在您的应用程序区域中起到作用

保持好奇心