views:

318

answers:

4

I am having a strange problem with boolean logic. I must be doing something daft, but I can't figure it out. In the below code firstMeasure.isInvisibleArea is true and measureBuffer1 is nil. Even though test1 is evaluating to NO for some reason it is still dropping into my if statement. It works ok if I use the commented out line. Any idea why this happens?

BOOL firstVisible = firstMeasure.isInVisibleArea;
BOOL notFirstVisible = !(firstMeasure.isInVisibleArea);
BOOL measureBufferNil = measureBuffer1 == nil;

BOOL test1 = measureBuffer1 == nil && !firstMeasure.isInVisibleArea;
BOOL test2 = measureBufferNil && !firstVisible;

if (measureBuffer1 == nil && !firstMeasure.isInVisibleArea)
//if (measureBufferNil && !firstVisible)    
{
    //do some action
}


Update 1:

I isolated the problem to !firstMeasure.isInVisibleArea as I've entirely taken on the measureBuffer bit. Inside isInVisible area is a small calculation (it doesn't modify anything though), but the calculation is using self.view.frame. I am going take this out of the equation as well and see what happens. My hunch is that self.view.frame is changing between the two calls to isInVisibleArea.


Update 2: This is indeed the problem. I have added the answer in more detail below

+2  A: 

If test1 is evaluating to NO as you say, then drop test1 into the if statement:

if(test1){
    //see if this executes?
}

See what that does.

Kevin Crowell
If I do this then it correctly doesn't drop into the if condition.
Ian1971
+5  A: 

When in doubt, you should fully parenthesize. Without looking up the precedence rules, what I think what is happening is that = is getting higher precedence than == or &&. So try:

BOOL test1 = ((measureBuffer1 == nil) && !firstMeasure.isInVisibleArea);
GoatRider
== has a higher precedance than assignment =http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
Jane Sales
+4  A: 

While you certainly can parenthesize, you should also know that nil objects evaluate to boolean NO and non-nil objects evaluate to boolean YES. So you could just as easily write this:

BOOL firstVisible = firstMeasure.isInVisibleArea;
BOOL notFirstVisible = !(firstMeasure.isInVisibleArea);
BOOL measureBufferNil = measureBuffer1;

BOOL test1 = !measureBuffer1 && !firstMeasure.isInVisibleArea;
BOOL test2 = measureBufferNil && !firstVisible;

if (measureBuffer1 && !firstMeasure.isInVisibleArea) {
    //do some action
}

You would end up with the same results. I agree with GoatRider, though. It's always far better to parenthesize your conditional expressions to clarify what you really want to happen than it is to rely on the language's operator precedence to do it for you.

Alex
benzado
I've removed measureBuffer entirely from the equation. The problem is with the firstMeasure.isInVisible area. I've updated the question with my latest findings
Ian1971
A: 

My hunch was correct, it is related to the view frame changing between calls to firstMeasure.isInVisible area.

This whole routine is called in response to the view moving. I think I need to grab the value of firstMeasure.isInVisibleArea at the start of the method and use that value throughout.

Phew. Boolean logic isn't broken. All is right with the world.

Thanks for all your input

Ian1971