See Avoid Causing Deallocation of Objects You’re Using in Advance Memory Management: Practical Memory Management, in which they point out that "received objects should typically remain valid throughout the scope of the calling method", i.e. retain
and release
are not necessary, except with the following caveat:
There are occasional exceptions to this rule, primarily falling into one of two categories.
When an object is removed from one of the fundamental collection classes.
heisenObject = [array objectAtIndex:n];
[array removeObjectAtIndex:n];
// heisenObject could now be invalid.
When an object is removed from one of the fundamental collection classes, it is sent a release
(rather than autorelease
) message. If the collection was the only owner of the removed object, the removed object (heisenObject
in the example) is then immediately deallocated.
When a “parent object” is deallocated.
id parent = <#create a parent object#>;
// ...
heisenObject = [parent child] ;
[parent release]; // Or, for example: self.parent = nil;
// heisenObject could now be invalid.
In some situations you retrieve an object from another object, and then directly or indirectly release the parent object. If releasing the parent causes it to be deallocated, and the parent was the only owner of the child, then the child (heisenObject
in the example) will be deallocated at the same time (assuming that it is sent a release rather than an autorelease
message in the parent’s dealloc
method).
To protect against these situations, you retain heisenObject
upon receiving it and you release it when you have finished with it. For example:
heisenObject = [[array objectAtIndex:n] retain];
[array removeObjectAtIndex:n];
// Use heisenObject...
[heisenObject release];
I'd be surprised if your helper function fell into one of those categories. You'll probably be fine without the retain
and release
, but I only mention it for the sake of full disclosure.
Obviously, you might need your own retain
and release
if your functions need it for other reasons (e.g. if task is asynchronous or if you are otherwise doing something unusual where the object must outlive the scope of the calling method), but I suspect you would have mentioned it if you were doing one of those things.
Also, if your utility function was creating and returning an object, then that would be a different matter (e.g. you'd generally autorelease
objects that you were returning).