我有这样的代码:
-(IBAction)send {
if ([self isCorrect1] && [self isCorrect2] && ...) {
[self sendRequest];
}
}
-(BOOL)isCorrect1 {
...
}
-(BOOL)isCorrect2 {
...
}
每个isCorrect
方法都会检查一些条件,在视图中显示一些消息并返回检查结果。我注意到,如果第一个条件为false,它将只显示第一个方法的错误消息(我需要检查所有这些消息)并且在这些方法中没有触发断点。我认为这是某种LLVM优化,所以我创建了这样的代码:
-(IBAction)send {
BOOL correct = [self isCorrect1];
correct = correct && [self isCorrect2];
...
if (correct) {
[self sendRequest];
}
}
仍然无法正常工作。我是否必须创建新的BOOL变量来存储结果以进行检查,还是有其他方式?
答案 0 :(得分:3)
由于第一个条件评估为false
,因此不会检查其余条件,并将立即转到else
部分。
试试这个。
BOOL finalResult = [self isCorrect1];
finalResult = [self isCorrect2] && finalResult;
finalResult = [self isCorrect3] && finalResult;
finalResult = [self isCorrect4] && finalResult;
...
if (finalResult) {
}
这将通过所有isCorrect
测试,并告知您最终是否通过了所有这些测试。
答案 1 :(得分:2)
您看到的行为是&&
的预期行为,即,在评估所有条件之前,如果它可以提前确定结果,则会将评估“短路”:
expression-yielding-false && something-else
上述结果完全由第一部分决定;无论第二个操作数产生什么,最终结果都是假的。这允许你写一些类似的东西:
if (obj != null && obj->count == 3)
{
...
}
如果&&
没有短路行为,则必须写
if (obj != null)
{
if (obj->count == 3)
{
...
}
}
||
有类似的行为。在
something-yielding-true || anything
右侧不会影响结果值,因为左侧已经返回true。
一种可能的解决方法是:
int succeeses = 0;
succeesses += [self isCorrect1]? 1 : 0;
succeesses += [self isCorrect2]? 1 : 0;
succeesses += [self isCorrect3]? 1 : 0;
if (successes == 3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
如果您需要知道,哪些测试通过,哪些测试失败,您可以尝试:
BOOL passed1 = [self isCorrect1];
BOOL passed2 = [self isCorrect2];
BOOL passed3 = [self isCorrect3];
if (passed1 && passed2 && passed3)
{
// All tests did succeed
}
else
{
// At least one failed.
}
以上更密集的版本将是
int passed = 0;
passed |= [self isCorrect1]? (1 << 0) : 0;
passed |= [self isCorrect2]? (1 << 1) : 0;
passed |= [self isCorrect3]? (1 << 2) : 0;
if (passed == 7)
{
// All tests did succeed
}
else
{
if (passed & (1 << 0))
{
// First test passed
}
else
{
// First test failed
}
if (passed & (1 << 1))
{
// Second test passed
}
else
{
// Second test failed
}
if (passed & (1 << 2))
{
// Third test passed
}
else
{
// Third test failed
}
}
这只是一个更为神秘的版本,每个测试都有一个布尔变量。