【问题标题】:Objective-C && doesn't short circuit for !varObjective-C && 不会短路 !var
【发布时间】:2015-02-15 11:12:17
【问题描述】:

尝试运行这个:

UIView *testView = nil;

NSLog(@"Take 1");
NSString *message = @"view doesn't exist";
if (!testView && !testView.subviews) {
   message = @"this message should never appear" ;
}
NSLog(message);


NSLog(@"Take 2");
message = @"view doesn't exist";
if (testView != nil && testView.subviews != nil) {
    message = @"this message should never appear" ;
}
NSLog(message);

NSLog(@"Take 3");
message = @"view doesn't exist";
if (!testView) {
    if (!testView.subviews) {
        message = @"this message should never appear" ;
    }
}
NSLog(message);

NSLog(@"Take 4");
message = @"view doesn't exist";
if (testView != nil) {
    if (testView.subviews != nil) {     
        message = @"this message should never appear" ;
    }
}
NSLog(message);

我得到的输出是:

Take 1
this message should never appear
Take 2
view doesn't exist
Take 3
this message should never appear
Take 4
view doesn't exist

为什么 Obj-C 不短路 !testView(在 Take 1 中)?

为什么在 Take 3 中 testView 明显为零时,它会进入!testView

我不应该测试 nil 对象的功能吗(例如,当我测试 subviews 时)?

【问题讨论】:

  • 你自己搞糊涂了。因为testViewnil,所以!testView 是真的。 !testView.subviews 也是如此。除此之外,Take 3 和 Take 4 的逻辑显然是相反的,所以你应该期待相反的结果。瞧,你得到了相反的结果。
  • 感谢@KenThomases,我已经删除了罪魁祸首。

标签: objective-c short-circuiting evaluate


【解决方案1】:

您看到的输出是正确的,并且短路行为也正常工作。

当计算布尔表达式时,如果表达式不为 0,则结​​果为真,如果为 0,则认为结果为假。因此,在您拥有if (something) 的任何地方,您都可以将其读作if (something != 0)! 运算符是否定的,所以如果你扩展它,你会得到以下第一种情况:!(testView != 0) && !(testView.subviews != 0)。可以去掉双重否定,得到(testView == 0) && (testView.subviews == 0),这显然是正确的(nil 也是 0)。

那里的短路也正确应用,你只是看不到它。为了证明您可以在测试中使用一些包装函数:

id testFunc( id value ) {
    NSLog(@"testFunc: %@", value );
    return value;
}

并在您的测试中使用它:if (!testFunc(testView) && !testFunc(testView.subviews))

简而言之,您对布尔非运算符! 的假设是错误的。它进入if (!testView),因为testView 是nil

【讨论】:

  • 换句话说,@Sven,在检查 nil 时。我应该写(var != nil),但绝不写(!var)??
  • 两者都检查nil(实际上),但意义相反。 (var == nil)(!var) 相同。 (var != nil)(var) 相同。当你想做英语中写成“如果 testView 存在”的事情时,你可以做 if (testView)if (testView != nil)。当你想做“如果testView不存在”时,你可以做if (!testView)if (testView == nil)
【解决方案2】:

这里没有什么奇怪的。我重写了你的代码,用testView 代替niltestView.subviews 代替nil(给nil 的消息返回nil)。

NSLog(@"Take 1");
NSString *message = @"if clause was false";
if (!nil && !nil) { // if(true && true)
   message = @"if clause was true" ;
}
NSLog(message); // outputs "if clause was true"


NSLog(@"Take 2");
message = @"if clause was false";
if (nil != nil && nil != nil) { // if (false && false)
    message = @"if clause was true" ;
}
NSLog(message); // outputs "if clause was false"

NSLog(@"Take 3");
message = @"if clause was false";
if (!nil) { // if (true)
    if (!nil) { // if (true)
        message = @"if clause was true" ;
    }
}
NSLog(message); // outputs "if clause was true"

NSLog(@"Take 4");
message = @"if clause was false";
if (nil != nil) { // if (false)
    if (nil != nil) { // if (false)
        message = @"if clause was true" ;
    }
}
NSLog(message); // outputs "if clause was false"

如果你想知道视图是否存在,你可以使用类似的东西:

if (testView) {
    NSLog(@"View exists a.k.a. testView != nil");
} else {
    NSLog(@"View doesn't exist a.k.a. testView == nil");
}

我建议只使用if (testView)if (!testView) 来检查对象是否存在。这是 Objective-C 社区的标准,读起来更清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 2012-02-10
    • 2022-12-09
    • 2011-06-26
    • 1970-01-01
    相关资源
    最近更新 更多