Objective-C && 不会为 !var 短路
Objective-C && doesn't short circuit for !var
尝试运行这个:
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
为什么 !testView
的 Obj-C 没有短路(在 Take 1 中)?
Take 3中testView明明是nil,为什么会进入!testView
?
我不应该测试 nil 对象的功能吗(例如,当我测试 subviews
时)?
您看到的输出是正确的,短路行为也正常工作。
当计算布尔表达式时,如果表达式不为 0,则结果被认为是 true,如果表达式为 0,则结果被认为是 false。因此,在任何有 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
.
这里没有什么奇怪的事情发生。我重写了您的代码,将 testView
替换为 nil
,将 testView.subviews
替换为 nil
(发送至 nil
return 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社区的标准,读起来更清楚。
尝试运行这个:
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
为什么 !testView
的 Obj-C 没有短路(在 Take 1 中)?
Take 3中testView明明是nil,为什么会进入!testView
?
我不应该测试 nil 对象的功能吗(例如,当我测试 subviews
时)?
您看到的输出是正确的,短路行为也正常工作。
当计算布尔表达式时,如果表达式不为 0,则结果被认为是 true,如果表达式为 0,则结果被认为是 false。因此,在任何有 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
.
这里没有什么奇怪的事情发生。我重写了您的代码,将 testView
替换为 nil
,将 testView.subviews
替换为 nil
(发送至 nil
return 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社区的标准,读起来更清楚。