Question

I have a BOOL property and at the start this property equals NO. I want to set this property to YES from the start of my program, but with opportunity to toggle it. For this, I made this getter:

-(BOOL)turn
{
    if(!_turn)
        _turn = YES;
    return _turn;
}

This getter set my turn property to YES, but it makes it "constant", always YES. Why?

I thought

if(!_turn)

construction is specially for the reason where you want set the "not set yet" object value

Can you answer me why this is so? And how can I set my property value to what i want. Thanks.

Was it helpful?

Solution

Look at your action table:

turn:     False          True
!turn   turn = YES      Do Nothing

When _turn is false, you flip it too true. When _turn is true, you do nothing (there's no else statement). Then you return the value of _turn. So yea, you are returning true in all cases.

To be honest, the design is not very good. If you want to set the initial value of the variable to a certain value, do that in the init method. Then provide another method that simply toggles the value:

-(BOOL) toggleTurn {
  _turn = !_turn;
  return _turn;
}

OTHER TIPS

Usually the lazy initialization technique is used with pointers to objects, not with primitive types. This because a BOOL has only two possibile states: NO and YES, there isn't the "undefined state" which is usually associated with nil for objects.

The reason why it doesn't toggle is that you aren't toggling it, you are just setting it to YES when it's equal to NO, but you aren't handling the case when it's equal to YES. If you want to toggle it just do that:

-(BOOL)turn
{
    return _turn= !_turn;
}

PS: Whoever could argue that your method isn't properly a getter, because you are altering the variable before returning it. So I suggest to just return _turn without toggling it, and to create another separated method to toggle the variable.

Also I would like to mention that what you are doing is not called lazy initialization, I'll show you a case of lazy initialization:

// In the interface:
@property(nonatomic,readonly) NSNumber* turnObject;
// In newer compiler versions it should be auto synthesized to _turnObject

// In the implementation: 
-(BOOL) turn
{
    // In this case I am not toggling it
    if(!_turnObject)        // Equal to if(turnObject==nil)
        _turnObject= @(NO); // Equal to _turnObject=[NSNumber numberWithBOOL: NO];
    return _turnObject;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top