views:

202

answers:

2

Ok, I know the answer to this question should be obvious, but I need a little push in the right direction.

I find myself writing a fair number of methods that follow the following pattern:

-(NSThing*)myMethod{

  NSThing *thing = [[NSthing alloc] init];
  // do some stuff with the thing
  return thing;
}

My question is, how do I handle the release of this object? Clearly I can't release it within the method.

+7  A: 

usually you would autorelease it

-(NSThing*)myMethod{

  NSThing *thing = [[NSthing alloc] init];
  // do some stuff with the thing
  return [thing autorelease];
}
newacct
+3  A: 

Autoreleasing is the easy way to get out of this, as newacct said. However, you should take into consideration the "ownership" of the object you're returning.

In Objective-C, the general rule of thumb is that any method with alloc, new, or copy in its name returns an object that is not autoreleased, while other methods (like class methods) pre-autorelease the object to be returned. So these three are not equivalent in terms of autorelease (although the compiler may do some magic and reduce them all to string constants anyway):

// Autoreleased
NSString *string1 = [NSString stringWithString:@"aString"];
NSString *string2 = [[[NSString alloc] initWithString:@"aString"] autorelease];

// NOT autoreleased
NSString *string3 = [[NSString alloc] initWithString:@"aString"];

Your code can take a similar approach, where you consider who owns the object you're returning. In the specific example you provided, the method is the one allocing and initing the object, so in general you're responsible for autoreleaseing [sic] it within your own method. However, if you were to write a method that takes a preexisting object and modifies it in some way, you would not own that object and would not be responsible for autoreleasing the returned object. (Doing so could actually cause problems down the road when the autorelease pool to which the object belongs gets drained.)

See also (thanks to Peter and Quinn in the comments!):

Tim
Technically, it should be any method that begins with “alloc” or “new” or contains “copy”, not “init”, although alloc is inevitably followed by init, but not all inits follow alloc. See <http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>
Peter N Lewis
In comments, putting < and > around links causes an extra escaped character at the end of the URL. Here is the same URL without angle brackets: http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
Quinn Taylor
`+stringWithString:` is generally reduced if the parameter is a literal string, but the same cannot be done for `+stringWithFormat:` — that method is guaranteed to return a distinct NSString instance.
Quinn Taylor
Thanks for the corrections and clarifications - updated.
Tim