views:

50

answers:

3

I use properties pretty much anytime my classes need iVars. For retained properties, I have grown accustomed to a specific way of using the accessor methods to alloc/initialize the actual iVars:

- (void)anInitOrAccessorMethod
{
  self.property = [[AClass alloc] init];
  [self.property release];
}

Anytime I need to set a non-autoreleased iVar, I use the above style of setting the property (which retains the object), then sending it a release message to offset the alloc+retain. This is in contrast to many community code examples I see, where people just set the iVars directly if the object is created using alloc/create, thus eliminating the extra release.

Besides the extra code overhead, are there any performance drawbacks to my style?

A: 

It's not bad performance wise since I wouldn't expect properties to be initalized in a tight loop anyway, but it can be done more efficiently if you have access to the field used as a backing store for that proerty.

- (void)anInitOrAccessorMethod
{
  self.property = [[AClass alloc] init];
  [self.property release];
}

The retain/release sequence in this case is as follows (as you have correctly described):

alloc: retainCount = 1 
retain: retainCount = 2  // (setter)
release: retainCount = 1

If you have access to the backing store (assuming that iVar is called property_) you can drop the unnescessary reatin/release calls (you mentioned that correctly too):

- (void)anInitOrAccessorMethod
{
  self.property_ = [[AClass alloc] init];
}

Because the property setter is not invoked, the retainCount will stay 1, providing the same behavior your code had.

But there's a difference in behavior: Directly accessing the backing store is safe for initializing the property (when it has been nil before) only, because the setter can no longer make sure a previous value will be released before the new value is set.

And performance wise: retain/release is really not a costly operation. Having no memory leaks is worth far more than possibly "saving" a retain/release call.

Johannes Rudolph
+3  A: 

Do not do that. If your property is declared as having copy semantics, your code will leak the first object and overrelease the second.

Jonathan Grynspan
Ah, yes, thanks for pointing that out.To clarify for anyone else who might read this...If you do this on a copy property, you get:[property release];property = [[[newObject alloc] init] copy];[property release];The last release ends up applying to the new copy, and newObject never gets released.
iPhoneToucher
A: 

The performance overhead is probably negligible, assuming your accessors don't have costly side effects, but that leads into the reason not to use accessors in -init. You want to avoid bugs from accessors that make assumptions about the state of the object.

Preston
You also want to not assume that the accessors themselves behave a certain way. The point Jonathan raised about `copy` properties is the most common way this could go wrong; another is that you may replace a synthesized accessor with a custom one later on, and still another is that a subclass may override the accessor.
Peter Hosey