Question

I understand that when using Alloc, new or copy you own the object and need to release the object. I understand that if I retain an object that I need to release it.

But if I have the following statment at the end of a method:

return [[UIImage alloc] initWithContentsOfFile:path];

I own the UIImage object becaused I allocated the memory space, but I dont have a reference to it anymore because it was returned to the caller. In my dealloc() method I can't release it, since I dont have a reference.

So my question is, is this correct:

return [[[UIImage alloc] initWithContentsOfFile:path] autorelease];

I beleive in this case the caller then can retain the returned object if they like to take ownership and will eventually need to release themselves.

Thanks for your help.

Was it helpful?

Solution

The whole point of autorelease was built around returning objects.

- (id)bad {
    MyObj *obj = [[MyObj alloc] init];
    return obj;
}

This code returns everything correctly, but you (as developer) must be sure to release the object later on.

- (id)moreBad {
    MyObj *obj = [[MyObj alloc] init];
    return [obj release];
}

This code uses the memory as expected, balancing retain and release in one scope, but returned object is garbage now (expect this to crash).

- (id)good {
    MyObj *obj = [[MyObj alloc] init];
    return [obj autorelease];
}

This code is "delayed release". I.e. you can retain the object at the caller side and the object would be safe. It could surely be broken if you don't have NSAutoreleasePool in scope, but that's a pretty rare condition, and you mostly know when that happens (the most common scenario is to start a new thread where there is no "default" autorelease pool).

So, the common practice is to balance the retain (and retain-like) and release methods in one scope. Next suggestion is to always have objects alloc-init-autoreleased, and switch to distinct releases if you have memory issues (like autoreleasing lots of objects in a loop). Next suggestion is to switch to ARC.

OTHER TIPS

Your assumptions are right. When you're returning an object, you should pass it as an autorelease object.

You use autorelease when you need to send a deferred release message—typically when returning an object from a method...

Both answers are correct, you may however not always have a convenience method at your disposal, so what I like to do is what you've done with autorelease:

- (MySomethingClass*)giveMeAFancyObject{
    MySomethingClass *obj = [[[MySomethingClass alloc] init] autorelease];
    obj.name = @"Something";
    // do some setting up maybe
    return obj;
}

If you use release, however, the string will be deallocated before it is returned (and the method would return an invalid object). Using autorelease, you signify that you want to relinquish ownership, but you allow the caller of the method to use the returned string before it is deallocated.

Why trying to alloc it? Just say:

return [UIImage imageWithContentsOfFile:path];

Nothing to alloc - nothing to release.

Also, this is the best option while using ARC, where a releasing attempt leads to error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top