objective-cpropertiesivar

Reason to use ivars vs properties in objective c


I have been unable to find any information on this topic and most of what I know about it has come by complete accident (and a few hours of trying to figure out why my code wasn't working). While learning objective-c most tutorials I have found make variables and properties with the same name. I don't understand the significance because it seems that the property does all the work and the variable just kind of sits there. For instance:

Test.h

@interface Test : NSObject {
    int _timesPlayed, _highscore;
}

@property int timesPlayed, highscore;

// Methods and stuff

@end

Test.m

@implementation Test

  @synthesize timesPlayed = _timesPlayed;
  @synthesize highscore   = _highscore;

  // methods and stuff

@end

What I know

1) Okay so today I found out (after hours of confusion) that no matter how much changing you do to the properties highscore = 5091231 it won't change anything when you try to call [test highscore] as it will still be returning the value of _highscore which (I think) is the ivar that was set in test.h. So all changing of variables in test.m needs to be changing _highscore and not highscore. (Correct me if I'm wrong here please)

2) If I understand it correctly (I probably don't) the ivars set in test.h represent the actual memory where as the @properties are just ways to access that memory. So outside of the implementation I can't access _highscore without going through the property.

What I don't understand

Basically what I don't get about this situation is whether or not I need to use the ivars at all or if I can just use @property and @synthesize. It seems like the ivars are just extra code that don't really do anything but confuse me. Some of the most recent tuts I've seen don't seem to use ivars but then some do. So is this just a coding preference thing or is it actually important? I have tried searching through Apple's Documentation but I get rather lost in there and never seem to find what I'm looking for. Any guidance will be greatly appreciated.


Solution

  • You can think of the syntax for synthesizing properties as @synthesize propertyName = variableName.

    This means that if you write @synthesize highscore = _highscore; a new ivar with the name _highscore will be created for you. So if you wanted to you could access the variable that the property is stored in directly by going to the _highscore variable.

    Some background

    Prior to some version of the compiler that I don't remember the synthesis statement didn't create the ivar. Instead it only said what variable it should use so you had to declare both the variable and the property. If you synthesized with a underscore prefix then your variable needed to have the same prefix. Now you don't have to create the variable yourself anymore, instead a variable with the variableName that you specified in the synthesis statement will be created (if you didn't already declare it yourself in which case it is just used as the backing variable of the property).

    What your code is doing

    You are explicitly creating one ivar called highscore when declaring the variable and then implicitly creating another ivar called _highscore when synthesizing the property. These are not the same variable so changing one of them changes nothing about the other.

    Should you use variables or not?

    This is really a question about preference.

    Pro variables

    Some people feel that the code becomes cleaner if you don't have to write self. all over the place. People also say that it is faster since it doesn't require a method call (though it is probably never ever going to have a measurable effect on your apps performance).

    Pro properties

    Changing the value of the property will call all the necessary KVO methods so that other classes can get notified when the value changes. By default access to properties is also atomic (cannot be accessed from more then one thread) so the property is safer to read and write to from multiple thread (this doesn't mean that the object that the property points to is thread safe, if it's an mutable array then multiple thread can still break things really bad, it will only prevent two threads from setting the property to different things).