禁止nil对象上的选择器

时间:2014-12-14 13:31:02

标签: ios objective-c cocoa

如何暂时禁止在nil对象上调用选择器。

实际上我得到了一个错误的访问异常,几个小时后我才知道我在使用数组时没有调用alloc-init。

我可以拥有类似的东西 prefix.h文件中的#define DISABLE_SELECTORS_ON_NIL_OBJECTS
或者某些复选框,某些位于项目设置中,或者某些异常可以禁用nil对象上的选择器,或者 我是否必须始终将代码放入if(object!= nil)?

2 个答案:

答案 0 :(得分:2)

错误的访问异常意味着您的未初始化的对象变量不是 nil。在Objective-C中,只有实例变量会自动归零。其他人保留该内存位置或上次使用时注册的任何值。唯一的解决方法是确保在使用变量之前对其进行初始化,即使这意味着将变量设置为nil

在代码上运行静态分析器。它经常可以找到这样的问题,并帮助您解决它们。

答案 1 :(得分:1)

简短回答:我不相信有任何简单的方法可以按照你建议的方式做到这一点。

答案很长:你可以在运行时抓住它......

如果您正在使用ARC,则所有Objective-C对象引用类型的变量将由运行时初始化为nil。然而,正如Eric Skroch所暗示的那样,访问权限可能不是nil

作为调试辅助工具,有各种环境变量可以设置为让Objective-C运行时在代码运行时打印出大量信息,请参阅Apple的Mac OS X Debugging Magic(该文档)引用iOS版本,但它似乎是MIA)。但是,似乎没有任何内容可以将消息捕获到nil

如果所有其他方法都失败,请使用断点...这是objc_msgsend(OS X)的开头:

libobjc.A.dylib`objc_msgSend:
0x7fff9774d240:  testq  %rdi, %rdi
0x7fff9774d243:  je     0x7fff9774d270            ; objc_msgSend + 48
0x7fff9774d245:  testb  $0x1, %dil
0x7fff9774d249:  jne    0x7fff9774d287            ; objc_msgSend + 71
0x7fff9774d24c:  movq   (%rdi), %r11
0x7fff9774d24f:  pushq  %rax
0x7fff9774d250:  movq   0x10(%r11), %r10
0x7fff9774d254:  movl   %esi, %eax
0x7fff9774d256:  andl   (%r10), %eax
0x7fff9774d259:  movq   0x10(%r10,%rax,8), %r11
0x7fff9774d25e:  incl   %eax
0x7fff9774d260:  testq  %r11, %r11
0x7fff9774d263:  je     0x7fff9774d29b            ; objc_msgSend + 91
0x7fff9774d265:  cmpq   (%r11), %rsi
0x7fff9774d268:  jne    0x7fff9774d256            ; objc_msgSend + 22
0x7fff9774d26a:  popq   %rax
0x7fff9774d26b:  jmpq   *0x10(%r11)
0x7fff9774d26f:  nop    
0x7fff9774d270:  movq   -0x19eb41e7(%rip), %rdi   ; _objc_nilReceiver
0x7fff9774d277:  testq  %rdi, %rdi
0x7fff9774d27a:  jne    0x7fff9774d245            ; objc_msgSend + 5
0x7fff9774d27c:  xorl   %eax, %eax

最后一条指令是第一条命令,当它确定接收器绝对是nil时。因此,如果您认为可能会向nil发出意外消息,您可以在该指令上断点 - LLDB文档会告诉您如何不知道。

HTH。