What is the difference between ivars and properties in Objective-C

20,331

Solution 1

Number 1 differs from the other two by forward declaring the MyOtherObject class to minimize the amount of code seen by the compiler and linker and also potentially avoid circular references. If you do it this way remember to put the #import into the .m file.

By declaring an @property, (and matching @synthesize in the .m) file, you auto-generate accessor methods with the memory semantics handled how you specify. The rule of thumb for most objects is Retain, but NSStrings, for instance should use Copy. Whereas Singletons and Delegates should usually use Assign. Hand-writing accessors is tedious and error-prone so this saves a lot of typing and dumb bugs.

Also, declaring a synthesized property lets you call an accessor method using dot notation like this:

self.otherObj = someOtherNewObject; // set it  
MyOtherObject *thingee = self.otherObj; // get it 

Instead of the normal, message-passing way:

[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it 

Behind the scenes you're really calling a method that looks like this:

- (void) setOtherObj:(MyOtherObject *)anOtherObject {

    if (otherObject == anOtherObject) {
        return;  
    }

    MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
    otherObject = [anOtherObject retain]; // put the new value in  
    [oldOtherObject release]; // let go of the old object
} // set it

…or this

- (MyOtherObject *) otherObject {  
    return otherObject;
} // get it

Total pain in the butt, right. Now do that for every ivar in the class. If you don't do it exactly right, you get a memory leak. Best to just let the compiler do the work.

I see that Number 1 doesn't have an ivar. Assuming that's not a typo, it's fine because the @property / @synthesize directives will declare an ivar for you as well, behind the scenes. I believe this is new for Mac OS X - Snow Leopard and iOS4.

Number 3 does not have those accessors generated so you have to write them yourself. If you want your accessor methods to have side effects, you do your standard memory management dance, as shown above, then do whatever side work you need to, inside the accessor method. If you synthesize a property as well as write your own, then your version has priority.

Did I cover everything?

Solution 2

Back in the old days you had ivars, and if you wanted to let some other class set or read them then you had to define a getter (i.e., -(NSString *)foo) and a setter (i.e., -(void)setFoo:(NSString *)aFoo;).

What properties give you is the setter and getter for free (almost!) along with an ivar. So when you define a property now, you can set the atomicity (do you want to allow multiple setting actions from multiple threads, for instance), as well as assign/retain/copy semantics (that is, should the setter copy the new value or just save the current value - important if another class is trying to set your string property with a mutable string which might get changed later).

This is what @synthesize does. Many people leave the ivar name the same, but you can change it when you write your synthesize statement (i.e., @synthesize foo=_foo; means make an ivar named _foo for the property foo, so if you want to read or write this property and you do not use self.foo, you will have to use _foo = ... - it just helps you catch direct references to the ivar if you wanted to only go through the setter and getter).

As of Xcode 4.6, you do not need to use the @synthesize statement - the compiler will do it automatically and by default will prepend the ivar's name with _.

Share:
20,331

Related videos on Youtube

ennuikiller
Author by

ennuikiller

29,200 ? I can calculate the motion of heavenly bodies but not the madness of people -- Sir Isaac Newton Time heals all wounds, but ultimately kills the organism.... -- paraphrased Hector Berlioz quote "Lloyd-Webber's awful stuff Runs for years and years and years An earthquake hits the theatre But the operetta lingers Then the piano lid comes down And breaks his fucking fingers It's a miracle" - Roger Waters What God Wants God Gets Succinctness is Godliness oh and just in case anyone is wondering: ennui - interminable boredom killer - a person or thing that kills ennuikiller - a person who kills interminable boredom About the avatar: It is in memory of 2 of the greatest geniuses of the 20th century (or perhaps in any century). 1. Peter Sellers whose comic genius inspired a whole slew of successful comedians and what better accomplishment to leave to the world than laughter!! 2.Stanley Kubrick whose films have been both iconoclastic and profoundly humanistic (I think some may have missed this point). I believe his crowning achievement is in fact Dr. Strangelove who is pictured in the avatar. A dark comedy (but with very serious overtones) about the ease with which the human species can eradicate itself. If you haven't seen it, do yourself a favor and watch it RIGHT NOW!

Updated on July 05, 2022

Comments

  • ennuikiller
    ennuikiller almost 2 years

    What is the semantic difference between these 3 ways of using ivars and properties in Objective-C?

    1.

    @class MyOtherObject; 
    @interface MyObject {
    }
    @property (nonatomic, retain) MyOtherObject *otherObj;
    

    2.

    #import "MyOtherObject.h"
    @interface MyObject {
        MyOtherObject *otherObj;
    }
    @property (nonatomic, retain) MyOtherObject *otherObj;
    

    3.

    #import "MyOtherObject.h"
    @interface MyObject {
        MyOtherObject *otherObj;
    }
    
  • ennuikiller
    ennuikiller over 13 years
    yes, thank you very much! One note I'd like to make is that if you take out the forward class pragma in #1 and replace it with an #import "MyOtherObject" you get a compile time error, not sure why though ....
  • Greg
    Greg over 12 years
    is there any advantage of using approach #2 over approach #1?
  • kayjay
    kayjay almost 12 years
    @Greg Method #1 will prevent a circular reference. See stackoverflow.com/questions/7221174/…
  • jscs
    jscs almost 12 years
    It should be noted that the atomicity of a property does not guarantee thread safety.
  • JeremyP
    JeremyP almost 12 years
    Nice answer except the bit about dot notation. You do not need to synthesise the property to use it for dot notation. In fact, you do not need to declare a property at all. As long as you have a declared setter and getter (e.g. setFoo: and foo) you can use dot notation.
  • David H
    David H almost 12 years
    So if I have an ivar that is atomic, you mean that while the setter is setting it or the getter is getting it, another thread kicks in and tries to do either, that it all gets foobared? Then what is the point of atomic? My understanding is that atomic at least makes sure that if you set an ivar, it gets set, its retain count is appropriate etc. Otherwise why atomic? [Not that it solves all problems just prevents you from getting foobared]
  • jscs
    jscs almost 12 years
    You're guaranteed to get a valid, whole object -- the getter won't return an object that is in the process of being deallocated -- but if another threads is using the setter, you may get the value from before or after. Specifying that has to be handled outside the getters and setters. In other words, no thread will be interrupted during the getter or setter operation, but the order of the operations is not (cannot be, at this level, AFAIK) defined.
  • David H
    David H almost 12 years
    Well, I would argue that your original comment was misplaced - the atomicity is honored, its just that accessing via threads can lead to a raft of problems - thus, every ivar I've ever declared is atomic and if there are threads involved then concurrency is dealt with elsewhere.
  • Sean Larkin
    Sean Larkin over 10 years
    For relevance, if using ARC, synthesize is done automatically.