views:

906

answers:

2

I am reading up about Encoding and Decoding and I noticed that sometimes people miss the retain off the end, I have also noticed that retain is sometimes used on some varables but not others. Can I ask ...

(1) What is the purpose of this retain and why is it sometimes not needed?

(2) Does the use of the retain imply that I need to match it with a release, and if so where?

- (id) initWithCoder: (NSCoder *) decoder {
    name  = [[decoder decodeObjectForKey: @"CardName"] retain];
    email = [[decoder decodeObjectForKey: @"CardEmail"] retain];
}

or

- (id) initWithCoder: (NSCoder *) decoder {
    name  = [decoder decodeObjectForKey: @"CardName"];
    email = [decoder decodeObjectForKey: @"CardEmail"];
}

gary

+9  A: 

Your first snippit represents the correct behaviour. The -decodeObjectForKey: method does not contain the word init, copy or new, so there is no promise made about whether the object returned will stay around, and if so for how long. If your object needs its ivars to stay around, it should -retain the objects it gets back from the decoder. This -retain will need to be balanced with a -release, which will be in your object's -dealloc method (so the object is created with some initial ivars which it retains, and it releases its ivars when it is destroyed). Like this:

- (void)dealloc {
  [name release];
  [email release];
  [super dealloc];
}

The retain/release dance is not needed:

  • if you're using garbage collection

  • if your object doesn't need to claim ownership of its ivars. That's not often the case; delegates usually aren't retained (but then usually aren't archived either), and properties declared with the assign modifier aren't either.

Graham Lee
I probably need another trip round the memory management guide, can I ask, if I alloc a simple class that contains a single NSString instance variable should I be releasing that in my dealloc or will it get released when I release the containing instance?
fuzzygoat
yes, you should retain the instance variable when it gets set and release it when it's no longer needed. I've got a blog post with a set of links to memory management articles: http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html
Graham Lee
Thank you Graham, I think I a getting there now, I have linked you blog post for future reference. Have a great weekend.
fuzzygoat
+3  A: 

You may also have been misled by people using properties as well. Its possible that you've seen people doing:

- (id) initWithCoder: (NSCoder *) decoder {
    self.name  = [decoder decodeObjectForKey: @"CardName"];
    self.email = [decoder decodeObjectForKey: @"CardEmail"];
}

which would be fine if name and email were defined as 'retain' properties. Of course, you then get into the argument about whether its legal/advisable to use property accessors in initialise/dealloc methods - some say yes, some say no, Apple seem to be on the side of no but haven't ever really given a good reason that I can see.

Jeff Laing