views:

754

answers:

3

Example:

- (NSString*) title {
    return [[title retain] autorelease];
}

The setter actually retained it already, right? and actually nobody should bypass the Setter... so I wonder why the getter not just returns the object? It's actually retained already. Or would this just be needed in case that in the mean time another objects gets passed to the setter?

+6  A: 

From here http://www.macosxguru.net/article.php?story=20030713184140267

- (id)getMyInstance
    {
        return myInstanceVar ;
    }

or

- (id)getMyInstance
{
    return [[myInstanceVar retain] autorelease] ;
}

What's the difference ? The second one allows the caller to get an instance variable of a container object, dispose of the container and continue to play with the instance variable until the next release of the current autoreleased pool, without being hurt by the release of the instance variable indirectly generated by the release of its container:

aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);

If the "get" is implemented in the first form, you should write:

aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];

The first form is a little bit more efficent in term of code execution speed. However, if you are writing frameworks to be used by others, maybe the second version should be recommanded: it makes life a little bit easier to people using your framework: they don't have to think too much about what they are doing…;) If you choose the first style version, state it clearly in your documentation… Whatever way you will be choosing, remember that changing from version 1 to version 2 is save for client code, when going back from version 2 to version 1 will break existing client code…

oxigen
A: 

I haven't seen this pattern before, but it seems fairly pointless to me. I guess the intent is to keep the returned value safe if the client code calls "release" on the parent object. It doesn't really hurt anything, but I doubt that situation comes up all that often in well-designed libraries.


Ah, ok. from the documentation smorgan linked to, it seems this is now one of the methods that Apple is currently recommending that people use. I think I still prefer the old-school version:

- (NSString *) value
{
    return myValue;
}

- (void) setValue: (NSString *) newValue
{
    if (newValue != myValue)
    {
       [myValue autorelease]; // actually, I nearly always use 'release' here
       myValue = [newValue retain];
    }
}
Mark Bessey
That depends. It’s an absolute requirement for properties that may be accessed from multiple threads, for instance. More generally, situations that don’t come up often are the ones that lead to really annoying head-scratchers.
Ahruman
I think I see what you're saying, with regards to multiple threads, since you could then have multiple independent release pools and run loops. I still think autorelease in the setter makes more sense in that case.
Mark Bessey
And in the case of multi-threaded access, I usually use [obj copy] - having separate instances of objects eliminates any chance of conflict.
Mark Bessey
+4  A: 

It's not just for cases where someone releases the container, since in that case it's more obvious that they should retain the object themselves. Consider this code:

NSString* newValue = @"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue

This looks reasonable, but if neither the setter nor the getter uses autorelease the "Go on to do something" part will likely crash, because oldValue has now been deallocated (assuming nobody else had retained it). You usually want to use Technique 1 or Technique 2 from Apple's accessor method examples so code like the above will work as most people will expect.

smorgan