6

Possible Duplicate:
What describes @property(…) best? What's that actually good for?

If I declare a variable in my class interface, I can use such variable anywhere on my class. Awesome.

If I use @property (retain) Something *myVar; I can access that variable with self.myVar... But, what is the difference? Is there a good reason I should use one method or another?

Community
  • 1
  • 1
Saturn
  • 17,888
  • 49
  • 145
  • 271
  • I believe it has to do with whether or not you want to create getter/setter methods, but don't quote me on that. It's common knowledge among the cocoa veterans, I'm sure someone'll answer this soon :) – Aurum Aquila Apr 09 '11 at 04:59

3 Answers3

5

Short answer: Encapsulation of memory management.

Longer answer: You need to establish ownership of an object if you want to use it later. If you want to use it later, you'll need a reference to it with which to do so, and a great place to keep that reference is in an instance variable.

You could handle the ownership claims (i.e. retains and releases) each time you assign a new value to that, but that would leave a lot of repetitious and trouble-prone boilerplate code scattered all over the place, like cherries in a fruitcake. That kind of mess is fiendishly difficult to debug when (not if) something goes wrong. So, it's far better to wrap that code up in accessor methods, so you can write it once and then forget about it.

But accessor methods are mostly boilerplate too, so we use @property declarations to create them automagically, rather than writing them by hand.

Edit: Apple's Memory Management Guide provides a lot of detail about what the accessor methods generated by @property do behind the scenes.

Sherm Pendley
  • 13,556
  • 3
  • 45
  • 57
  • So the first method I mentioned does not establish ownership if an object and therefore I might lose it in the future? I guess I'll just use properties for everything =/. One last thing: if I use self.myProperty = nil in the Dealloc method (when I no longer need it) I'm fine, right? I don't have to say [self.myProperty release] or anything? – Saturn Apr 09 '11 at 05:10
  • No, ownership is established by creating an object with +alloc, -copy, or -mutableCopy, or by sending it a -retain message. No matter how you establish ownership, you must give it up by sending a -release message. And there's the rub - every time you assign a new value to your instance variable, you need to release the old one, and you need to make sure that all of these ownership claims stay balanced. – Sherm Pendley Apr 09 '11 at 05:13
  • It's easiest to do that by avoiding creation methods that establish ownership, or using -autorelease when you must use them, and simply letting the property assignment handle the rest. – Sherm Pendley Apr 09 '11 at 05:14
  • The common wisdom is to avoid property assignments in -dealloc though, because they can have side effects - for example if a property is being observed via cocoa bindings. In dealloc, you should [myProperty release]; and myProperty = nil; - i.e. bypass the generated accessor method and assign directly to the instance variable. – Sherm Pendley Apr 09 '11 at 05:15
  • Ah, so I have to use [self.myProperty release] as well..... interesting, thanks. I'll read that Apple documentation too :) – Saturn Apr 09 '11 at 05:23
  • You only need to work directly with the instance variable in -dealloc, and you do it there without the self., i.e. `[myProperty release]`. Anywhere else, doing a `self.myProperty = nil` is the way to go. The setter method created by the @property will release the old value, and assign the new (nil) value to the instance variable. – Sherm Pendley Apr 09 '11 at 05:25
  • Has this changed with the arrival of ARC? – Van Du Tran Dec 19 '13 at 15:01
1

If I use @property (retain) Something *myVar; I can access that variable with self.myVar... But, what is the difference?

@property (retain) Something *myVar;

// this property declaration declares:
- (Something *)myVar;
// and 
- (void)setMyIvar:(Something *)arg;
// and is accessible by dot syntax.
// it also declares and/or documents how the ivar is managed (copy, retain, etc.)

in use:

// direct access to the ivar. zero additional overhead (with regard to accessing the ivar)
[myVar message];

// properties used with dot syntax invoke the accessor. therefore,
[self.myVar message];
// is the same as:
[[self myVar] message];

the property's properties also give instructions to the compiler as to how to synthesize an accessor.

Is there a good reason I should use one method or another?

in init and dealloc, access the ivar directly - you are interested in initialization and cleanup of the object's ivars and do not care about subclasses. using properties here can also introduce bugs or undefined behavior.

for other cases, that is, when the object is in a fully constructed state, you should always use the accessor for consistency. if a subclass overrides an accessor, direct access of the ivar could break designs.

if you want to avoid this, then make the ivar private and do not declare a property for it. if you do declare a property for it, then document that it is private; i'll typically write @property (retain) Something * private_myIvar; in this case. in this case, it is convenient to use a property to synthseize the ivar's memory management.

when the ivar is private, you have total access to it. it is safe to access directly or by private property. otherwise, assume that you must use the accessor.

if myIvar is declared private and will be created only at initialization, you can avoid declaring the properties altogether. this will reduce runtime overhead (if that is critical). messaging overhead, retain/release cycles, and atomics will (naturally) require more execution time. so it can be bypassed to improve performance.

visibility/maintenance. sometimes, it's far less maintenance/implementation to hide an ivar from the interface. in other cases, the ivar is an implementation detail of the class, and should not be a part of the public interface. in such cases, consider making it private (there are a few ways to accoomplish this in objc).

justin
  • 104,054
  • 14
  • 179
  • 226
0

Using the @property to access your ivars, does a lot of the repetitive code of releasing and retaining objects for you. You don't have to use them. It's just a lot of tutorials make it simple for people that are new to the platform.

Black Frog
  • 11,595
  • 1
  • 35
  • 66