【问题标题】:What happens if you pass nil at runtime to a parameter that shouldn't accept that?如果在运行时将 nil 传递给不应接受的参数会发生什么?
【发布时间】:2012-12-13 23:26:28
【问题描述】:

假设我有一个采用 CLLocationCoordinate2D 的方法。我不能在代码中直接将 nil 传递给它;编译器抱怨。但是,以下编译。那么运行时会发生什么?

CLLocation* loc = nil;
[self passMeCoordinates:loc.coordinate];

【问题讨论】:

  • 它可能会被悄悄地忽略,它可能会导致我们所知的宇宙终结。基本上,除非以某种方式记录在案,否则它是“未定义的行为”。
  • 当然,“坐标”是一个属性,所以会使用空指针进行调用,返回零。编译器可能会尝试从位置 0 复制位置坐标结构,您会收到存储错误。
  • @HotLicks 过去是结果未定义,但最近似乎发生了变化。 (见下面我的回答。)

标签: iphone objective-c ios location cllocationmanager


【解决方案1】:

这是一个有趣的问题。我假设您之前的代码是:

[self passMeCoordinates:nil];

编译器会抱怨这一点,因为 CLLocationCoordinate2D 不是对象。这是一个 C 风格的结构。因此,您不能在需要结构的地方传递对象/指针(nil)。 (它们的大小不同等)

如果我将您的代码稍微解释为:

CLLocation* loc = nil;
CLLocationCoordinate2D coord = loc.coordinate;
[self passMeCoordinates:coord];

问题归结为“coord 有什么价值”。您可能知道,Objective-C 中的规则是,如果您向 nil 发送消息(就像我们在这里所做的那样 - loc.coordinate 等价于 [loc coordinate]),那么您将返回 0。但是如果我们'重新期待一个结构?正如我刚才提到的,它与整数的大小不同。好吧,事实证明结果取决于您使用的编译器:

LLVM 3.0+ (Xcode 4.2+):返回全零,所以它相当于 (0,0) 的坐标:Can I rely on nil UIView returning CGRectZero for its frame?

LLVM 早期/GCC:一个结构可以填充垃圾/未定义的内容,所以它可以是任何东西。

【讨论】:

  • 这很有趣,但与 0,0 协调。嗯,这是一个有效的海中坐标。我不认为它等同于 nil。
  • 是的,同意,但就是这样。
【解决方案2】:

Loc.coordinate 是一个结构,因此您不能为此传递 nil。
并且返回 C 结构的方法在 nil 上调用是不安全的。 因此,您的警告不是关于将 nil 作为参数传递。

关于你关于 nil 作为论点的问题。好吧,这取决于方法,有些可以优雅地处理 nil ,有些则不会。如果您可以或不能将 nil 作为参数传递,请参阅通常所说的那些方法的文档。

【讨论】:

【解决方案3】:

正如其他人所指出的,您正在处理您的location 对象的struct 属性,因此nil 将是有问题的。您应该只对对象使用 nil

但更一般地说,你永远不应该假设任何方法都会接受nil 作为参数。这一切都因方法而异。对于内置类,它通常会在文档中指定nil 参数何时可接受。如果它没有说nil 是允许的,那么明智的做法是假设它不是。

您自己的代码是否接受nil 参数完全取决于您对该参数所做的操作,以及您是否正在执行任何要求它不是nil 的操作,您的代码是否正在检查非@987654330 @值和适当处理等。

作为一个完全随机的例子,如果你有一个方法:

NSMutableArray *array = [NSMutableArray array];
[array addObject:text];

如果textnil,这将生成NSInvalidArgumentException 异常。

归根结底,这一切都因方法而异。请参阅相关方法的文档以查看是否允许使用 nil

“不要使用nil,除非文档说明可以”规则的一个一般例外是,当向nil 对象发送消息时(即在nil 对象上调用方法) .这是允许的(但显然什么都不做)。正如文档所说:

在 Objective-C 中,您通常可以向nil 发送消息而不会产生不良影响。只要将返回的内容键入为对象,就可以保证发送到 nil 的消息的返回值有效。

【讨论】:

  • 同意,但他没有在这里传递 nil,因为 CLLocationCoordinate2D 不是对象。
  • @JesseRusak 绝对。我只是想回答我怀疑的更普遍的问题(其他人已经充分回答了struct 问题)。我只是不希望 OP 得出结论“哦,他们说我不能将 nilstruct 一起使用”,因此错误地认为当它不是 struct 时它是允许的。我试图澄清我的答案。
  • 酷,有道理。 +1
【解决方案4】:

在运行时 nil 会被传递给你的方法。编译器不做运行时检查,它只做编译时类型检查。

【讨论】:

  • 你确定吗? CLLocationCoordinate2D 不能为零;这是一个结构。
猜你喜欢
  • 2016-10-17
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 2012-01-03
  • 2022-11-26
  • 1970-01-01
  • 2023-04-04
  • 2020-12-17
相关资源
最近更新 更多