retain and autorelease in a getter method
Asked Answered
J

2

6

I am learning memory management, but I don't really understand why I should implement my attribute getter like this:

-(Weapon*)myWeapon
{
    [myWeapon retain];
    [myWeapon autorelease];
    return myWeapon;
}

I understand what I wrote, but I can't imagine why it is important? Can you please explain why I should do this?

Jackscrew answered 12/2, 2011 at 23:47 Comment(0)
E
10

This is from the Memory Management Programming guide:

Technique 1 In technique 1, values returned by the getter are autoreleased within the calling scope:

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

- (void) setTitle: (NSString*) newTitle {
    if (title != newTitle) {
        [title release];
        title = [newTitle retain]; // Or copy, depending on your needs.
    }
}

Because the object returned from the get accessor is autoreleased in the current scope, it remains valid if the property value is changed. This makes the accessor more robust, but at the cost of additional overhead. If you expect your getter method to be called frequently, the added cost of retaining and autoreleasing the object may not be worth the performance cost.

Technique 2 Like technique 1, technique 2 also uses an autorelease technique, but this time does so in the setter method:

- (NSString*) title {
    return title;
}

- (void) setTitle: (NSString*) newTitle {
    [title autorelease];
    title = [newTitle retain]; // Or copy, depending on your needs.
}

The performance of technique 2 is significantly better than technique 1 in situations where the getter is called much more often than the setter.

Technique 3 Technique 3 avoids the use of autorelease altogether:

- (NSString*) title {
    return title;
}

- (void) setTitle: (NSString*) newTitle {
    if (newTitle != title) {
        [title release];
        title = [newTitle retain]; // Or copy, depending on your needs.
    }
}

The approach used by technique 3 is good for frequently called getter and setter methods. It is also good for objects that do not want to extend the lifetime of their values, such as collection classes. Its disadvantage is that the old value may be deallocated immediately (if there are no other owners), which will cause a problem if another object is maintaining a non-owning reference to it. For example:

NSString *oldTitle = [anObject title];
[anObject setTitle:@"New Title"];
NSLog(@"Old title was: %@", oldTitle);

If anObject was the only object that owned the original title string, then the string will be deallocated after the new title is set. The log statement would then cause a crash as oldTitle is a freed object.

EDIT: Basically the point of retaining and then auto-releasing is to ensure that the object won't get deallocated if the property value is changed before the calling scope has a chance to retain it. This isn't usually an issue unless you've got asynchronous code. In most situations - (Weapon *)myWeapon { return myWeapon; } is just fine (plus it's faster).

Epner answered 12/2, 2011 at 23:58 Comment(2)
million THX Rich, last question : this techniques are recommended only in the getters and/or setters ???Jackscrew
what do you mean only getters and setters, where else do you want to use them? if you're asking whether it's ok do do this instead of using getters and setter, the answer is no. Always use getters and setters unless the vars are readonly, in which case you should use technique 3 (or just assign it if it's not an object ie. C data types) to set the variables in the initializer (readonly variables will never be changed so you don't need to autorelease).Epner
S
2

As ACBurk says, but there is a good description here:

http://vgable.com/blog/2009/03/31/how-to-write-cocoa-object-getters/

Syllabogram answered 12/2, 2011 at 23:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.