【问题标题】:Null different from false in booleans?布尔值中的 null 与 false 不同?
【发布时间】:2012-01-12 20:35:52
【问题描述】:

我有一个方法来构造一个发布请求。该请求可能有 x 个参数,但没有一个是强制性的。有布尔类型的参数(这些参数作为字符串传递,值为“true”或“false”(不是我的决定,它是一个 API)。

这就是问题所在。我的方法声明包含作为发布请求的一部分接受的所有参数。问题是如果布尔参数为真、假或不存在,请求会返回不同的结果。

我的方法 id 类似于

-(void) createRequestWithID:(NSString *)id translate(NSNumber *)translate onlyLastVersions:(NSNumber *)onlyLastVersions

我的方法是框架的一部分,将被其他开发人员使用和调用。这意味着,我无法控制它们传递给参数的内容,例如 translate 这是一个布尔值(我使用 NSNumber 作为包装器)。

问题来了。我需要能够确定该方法是否被称为将翻译为真、假或无。因为对于这些情况,我将请求作为 translate="true"、translate="false" 或 translate 将不存在于请求中。

我需要一种方法来区分真、假和无。

在 gbd 上进行测试以尝试找到一种区分它的方法:

(gdb) p translateFALSE $5 = (NSNumber *) 0x0

(gdb) p translateNIL $6 = (NSNumber *) 0x0

(gdb) po translateFALSE 无法打印 NIL 对象的描述。

(gdb) po translateNIL 无法打印 NIL 对象的描述。

(gdb) po [translateFALSE 类] 无法打印 NIL 对象的描述。

(gdb) po [translateNIL 类] 无法打印 NIL 对象的描述。

所以我看不出有什么办法。

【问题讨论】:

  • 下面的所有三个答案都解释了如何做到这一点,我的给出了两个工作代码示例。您不能将对象设置为false,这与将其设置为nil 相同。您可以在调试输出中看到,对象指针指向 0x0 -- NULL。有关创建数字的信息,请参阅 NSNumber 的文档,但您必须创建如下数字:NSNumber* n = [NSNumber numberWithBool:NO];

标签: objective-c pointers boolean null


【解决方案1】:
if( translate ) {
  if( [translate boolValue] ) {
    // translate is present and is set (YES)
  } else {
    // translate is present and is not set (NO)
  }
} else {
  // translate is nil / not present
}

如果你更喜欢让它看起来更像一个三路分支:

if( [translate boolValue] ) {
  // translate is present and is set (YES)
} else if( translate ) {
  // translate is present and is not set (NO)
} else {
  // translate is nil / not present
}

【讨论】:

  • 它不起作用,因为 nil 被评估为 false,因此,即使是 NSNumber,如果开发人员传递 false,对象也是 nil。无论如何,我尝试了这段代码来确认(使用 translate=nil 和 =false): NSNumber *translates=nil; if( [翻译 boolValue] ) { NSLog(@"YES"); } else if( 翻译 ) { NSLog(@"NO"); } 其他 { NSLog(@"NIL"); } } 这两种情况,输出都是 NIL
  • @yowie 因为您不能将对象指针设置为false。首先,您的编译器应该抱怨将整数转换为没有强制转换的指针。其次,您需要这样做:NSNumber* translate = [NSNumber numberWithBool:NO]; 它将评估中间块。
  • @yowie 至于设计你的框架......告诉程序员传递 nil 意味着他们根本不想设置那个特性,传递一个 NSNumber 对象设置为 false 意味着他们特别希望它是错误的。您可以与开发人员沟通如何正确使用您的 API,并由他们来实际正确使用它。如果您对此非常担心,请使用选项字典而不是直接传递对象。如果用户没有设置翻译键,他们就不会关心它。
  • 感谢您的 cmets 并同意理想情况下开发人员会通过 [NSNumber numberWithBool:NO];。不幸的是,我不能保证,我的问题仍然没有得到回答。此外,我可以通过将 NSNumber 设置为 false 来确认编译器不会抱怨,甚至不会发出警告。
  • @yowie 编译器没有生成警告太糟糕了。将NSObject 指针设置为false 与将其设置为nil 完全相同。这的答案。这是您测试对象是YESNO 还是nil 的方法。您将对象指针设置为false 是您的编程错误。在框架中你能做的只有这么多来保护程序员不犯编程错误。如果您对此感到担心,请使用字典来传递选项。
【解决方案2】:

对于布尔值没有 NULL(或 nil)之类的东西——NULL 是一个指针值。 NSNumber 可以为 nil,但表示 BOOL NO 的 NSNumber 不会为 nil。

【讨论】:

  • 请查看我添加到问题中的信息。 GBD 表明将 nil 或 false 传递给 NSNumber 会产生相同的结果,这就是我的问题。如果我要调用该方法,我肯定会传递一个表示 NO 的 NSNumber 对象,但其他开发人员会调用它,他们可能会传递 false
【解决方案3】:

如果你传递的是一个 NSNumber,那就是一个对象。您可以轻松区分拥有对象或拥有 nil 值。 (在尝试提取对象值之前执行此操作。)

【讨论】:

  • 问题是这个方法被其他开发者调用了。如果传递 false 或 nil,编译器不会抱怨,开发人员会做正确的事情(传递 false 是因为他想要包含 translate="false" 的请求或传递 nil 是因为他想要不带参数 translate 的请求。问题是我无法区分开发人员传递 false 或 nil 以知道我是否需要忽略请求中的参数或将其设置为 false
  • @yowie -- 我不明白你的要求。如果他想指定值,您的调用者将传递一个 NSNumber true 或 false,否则传递 nil。在尝试引用对象的值之前测试 nil。
  • 这是我的第一个想法。但是,测试 false 或 nil 的行为是相同的。例如:if(translate==false) 的行为与 if(translate==nil) 相同,这就是问题
  • 不,他们确实表现相同。一个 false 不会是 nil。首先测试 nil。
  • 是的。正如我告诉你的那样,我对它进行了肯定的测试,你也可以看到@Jason Coco 的回答。不过谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-02-21
  • 2015-08-18
  • 2017-06-26
  • 2019-12-11
  • 2013-09-02
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多