views:

186

answers:

1

I always see example code where in the viewDidLoad method, instead of saying, for example

someInstanceVar = [[Classname alloc] init];

they always go

Classname *tempVar = [[Classname alloc] init];
someInstanceVar = tempVar;
[tempVar release];

Why is this? Isn't it the exact same thing, just longer?

+11  A: 
e.James
my bad, fixed the code example. Still don't get why they do this.
marty
There is a key difference between `instanceVar = value` and `this.instanceVar = value`. Using the dot notation tells the compiler to invoke the property accessor, which takes care of the memory management automatically behind the scenes.
e.James
okay so the dot notation invokes the property accessor, and without the dot it just sets the instance variable?...I miss java...
marty
Don't you usually use `self.[…]`?@marty: The `self.instanceVar` accesses a property set in the `.h`-file. This will also `retain` the new value of `instanceVar`.
Emil
@marty: Yes, that is correct `:)` It's a tricky concept at first, but if it bites you once you'll never forget.
e.James
@e.James @marty No, it's not entirely correct. You need the entire `self.`-part to actually access the property.
Emil
oh so since it's using the property accessor, it's retained. But I'm still not sure about the original problem. What's the difference between making a temp and just straight initializing the instance variable?
marty
@marty: I added some more details to my answer, which I think may help explain. You *can* assign directly to the instance variable as in your very first example, but this leaves you open to errors down the road. One potential problem is that the old value in `instanceVar` is not released before the new one is assigned. Obviously that isn't a problem if there was no value in `instanceVar`, but rather than rely on that assumption, it is easier to always use the "alloc, set property, release" pattern and sleep easy.
e.James
You explained how assigning to properties is different, but not the reason why it's assigned to a temporary var before it's given to the property - why not simply this.propertyVar =[[SomeClass alloc] init]?
CiscoIPPhone
that's what I'm wondering.
marty
Good question. You have to use the intermediate variable so that you have something to release when you are finished. If you call 'self.propertyVar = [[Someclass alloc] init];', you can very easily leak the new object. Say, for example, that 'propertyVar' was a copy property. The property accessor would then dutifully copy that new object, and the *copy* would be properly released in your 'dealloc' method, but the original would simply be leaked.
e.James
I understand now, thanks e.James.
CiscoIPPhone
My pleasure. I'm glad you brought up that last point. I've been doing this for so long, I sometimes forget to explain some of the details.
e.James
Surely you mean `self` rather than `this`?
Chuck
@Chuck: Argh. Yes, surely I do. Thank you for spotting that.
e.James
The advice to avoid usage of autorelease on iPhone is probably the most misunderstood pieces of advice on the Apple web site. In this case, for example, autoreleasing the newly created instance will likely have minimal impact, because it is probably supposed to survive the end of the current run loop event anyway. Avoiding autorelease is a case of premature optimisation and is thus partly the root of all evil.
JeremyP
@JeremyP: It's a tricky issue. Even in this example, autorelease would be perfectly harmless if this block of code was only called a couple of times. However, if the same block of code was called from within a loop, the effects could be quite severe. Since it is very difficult to guarantee that a particular block of code will not be called from within a loop, the easiest way to be safe is to avoid autorelease altogether.
e.James
@JeremyP: I wouldn't really call this an optimization issue. It's more like the use of `goto`: while it is certainly *possible* to use it without causing problems in your code, it is definitely safer *not* to use it at all.
e.James
@e.James: if, if, if... *profile* to find out the issues and optimise when you *know* there is a problem. In any case, wrapping each iteration of the loop in an autorelease pool might be a better answer than jumping through hoops to avoid autorelease.
JeremyP
@JeremyP: I agree that premature optimization should be avoided, but I don't see the `alloc/init`, assign, `release` pattern as an *optimization*. To me, it is more of a convenience and safety issue. If you always use this pattern, you never have to worry about the potential side effects of autorelease.
e.James
@e.James: not all optimisation is about speed. There is also optimisation for memory footprint. alloc/init and release are potentially more dangerous than autorelease in most situations since there is more potential for memory leaks. For instance, -stringWithFormat: gives you an autoreleased object that you can forget about after you have used it, but alloc/initWithFormat: requires you to assign a temp variable and release the temp variable later. The code is uglier and if you forget the release - memory leak.
JeremyP
@JeremyP: I'm familiar with the different types of optimization, and I can certainly see your side of this issue: autorelease is avoided in order to keep temporary memory usage down, which is a memory footprint optimization. If your app was the only one running on the device and you could easily profile for the majority of the usage cases, there would be little reason to avoid autorelease.
e.James
My take on this is that since the iPhone and other iDevices are memory-constrained, and you never know how much room you will have, the safest bet is to avoid autorelease. Apple's dev tools do a pretty good job of finding any memory leaks that you might introduce with temporary variables.
e.James