【问题标题】:Is there a way to trap messages sent to nil in Objective-C?有没有办法在 Objective-C 中捕获发送到 nil 的消息?
【发布时间】:2010-10-29 04:30:54
【问题描述】:

我刚刚被一个烦人的bug 咬住,它被 Objective-C 中的“向 nil 发送消息是可以的”行为变得模糊不清。

我见过Sending a message to nil?,共识似乎是“这就是我们在Objective-C 中的滚动方式”。

现在,也许我在 Objective-C 方面没有足够的经验,但似乎将其困住会很有用,因为我想不出为什么会发生这种情况的充分理由 大多数 的时间。但是,这可能只是我不习惯的编码习惯。

除了像这样到处检查 nil 之外:

assert( object != nil );
[object message];

有没有办法让运行时捕获这种情况,并在object 为 nil 时发出警告?

【问题讨论】:

  • 为什么不尝试用 Objective-C 的习语来编写,而不是将 Java 的习语移植到 Objective-C?
  • 我不知道,我不会用 Java 编写代码。显然其他人发现这很有用(请参阅下面的答案)。
  • s/Java/另一种编程语言/。学习任何环境的本地习语通常会让你在那个环境中更有效率。不要与你的工具作斗争。
  • 我只是在问。这就是 stackoverflow 的用途。

标签: objective-c debugging null


【解决方案1】:

您可以使用ObjC undocumented trick or dtrace(请参阅 cmets 了解 dtrace 解决方案)。

pid$1::objc_msgSend:entry
/arg0==0/
{
  ustack();
}

【讨论】:

  • 太棒了。当我的眼睛停止流血时,我会试一试:-)
【解决方案2】:

nil 消息传递在 ObjC 中非常常用。人们可以争论这是好是坏;这只是你必须习惯的事情。如果你试图用技巧来打破它,那么你就会打破 Cocoa,因为 Cocoa 使用了它。有一些技巧(如 diciu 发布的)可以在您怀疑 nil 消息但似乎无法找到它的情况下进行调试。但是你不能只把这些留在你的代码中(上面的博客文章清楚地说明了这一点)。 nil 消息传递在框架中太常见了。

不过,比较一下你原来的观点:

- (void)doSomethingWith:(id)x {
    NSAssert(x != nil, @"Don't pass me nil");
    [x something];
}

对比

void Bar::DoSomething(Foo *x) {
    assert(x != NULL);
    if (x != NULL) {
       x.something;
    }
}

在这两种情况下,您都需要进行测试,并且在这两种情况下,如果您测试失败,编译器都不会警告您。唯一的区别是你在什么情况下崩溃/断言。就个人而言,我在NSAssert() 周围编写宏,使其总是在失败时打印一条日志消息。它只是在调试中崩溃。这样,当客户向我发送日志时,我可以看到哪些断言失败了。

【讨论】:

  • 谢谢 Rob,为了简洁起见,我只是包含了硬断言——我不喜欢发布构建断言崩溃。我认为整个 send-message-to-nil 事情我都会习惯的。尽管如此,值得询问和了解更多关于幕后发生的事情 - 每个人都赢了!
猜你喜欢
  • 1970-01-01
  • 2010-09-14
  • 2021-07-23
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
相关资源
最近更新 更多