It's not really necessary to declare properties for all ivars. A few points come to mind:
init
and then release as necessary during dealloc
.So I generally use properties, but for things like a NSMutableArray
that an object allocates during init
and uses to hold a bunch of whatevers, I'll use a plain old ivar since I'll never be reassigning the ivar.
While Daniel's answer is correct, I think it misses an important point. Namely:
I find that using properties instead of plain old ivars just takes too much code and I don't really see the benefits if you're comfortable with memory management.
The benefits are consistency; consistent memory management and consistent behavior.
Notably, these two lines of code can actually have extremely different behavior at runtime:
iVar = [foo retain];
self.iVar = foo;
The first is a direct setting of the instance variable and there will be no change notifications. The second goes through the setter and, thus, preserves any subclass customizations upon set and ensures that any observers of the property are notified of the change.
If you are using ivars directly throughout your code (internally to the class -- if you are using ivars of an instance directly from outside that instance, well... any contractor working on your codebase should double their rates ;), then you must either also handle change notification propagation manually (typically by calling willChangeValueForKey:
/didChangeValueForKey
) or explicitly engineer your application to avoid use of mechanisms that rely upon Key-Value Observation.
You say "takes too much code". I don't see that; in the above two lines of code, the dot syntax is fewer characters. Even calling the setter method using traditional syntax would be less code.
And do not discount the value in centralizing memory management; one accidental omission in a myriad of call sites and crash city.
Property are just syntax sugar that avoid you to write same methods over and over. With a property you have a setter that release the old object and retain the new one for free.
For the private fields - I suggest it is safe to use direct ivars only for primitive types (BOOL/int/float etc). I find a good practice wrapping everything related to memory-management in properties - even rarely-used fields. Additional bonus of this approach is that IDE usually highlights direct ivars access differently, so you always have a nice separation of simple scalar fields and object-type fields.
Contrary to this I would strongly discourage any direct ivars in the class public interface. Because of the dynamic nature of language it can lead to runtime errors that are extremely hard to find, localize and fix. Consider the following hierarchy
@interface BaseControl
...
@end
@interface Label : BaseControl
...
@end
@interface Button : BaseControl {
@public
BOOL enabled;
}
@end
and a code snippet
- (void)enableAllButtons {
NSArray *buttons = [self getAllButtons]; // expected to contain only Button instances
for (Button *button in buttons) {
button->enabled = YES;
}
}
Now imagine there's an error somewhere in -getAllButtons logic and you also get some Label's returned in that array - so those Label class instances will get missing ivar assigned. The fact that may be surprising is that -enableAllButtons will not crash in that case. But at that point those Label instances internal structure is corrupted and this will cause undefined behavior and crashes when they are used elsewhere.
Like some popular problems with memory management (and in general - with dangling pointers) - this kind of problems is hard to find and localize - because the appearance of the error usually is distant (in terms of time, code or app flow) from the place, causing the error. But with that particular problem you even don't have handy tools (like leak/zombies analyzers etc.) to help you localize and fix it - even when you learn how to reproduce it and can easily investigate erroneous state.
Obviously if you use @property (assign) BOOL enabled;
you'll get an easy-to diagnose and fix runtime exception in -enableAllButtons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With