views:

155

answers:

3

I have following simple class:

@interface Article: NSObject {
    NSString *title;
}
@property (copy, nonatomic) NSString *title;
@end

@implementation

- (void)setTitle:(NSString *)aString {
    if ((!title && !aString) || (title && aString && [title isEqualToString:aString])) return;
    dirty = YES;
    [title release];
    title = [aString copy];
}

- (NSString *)title {
    return title;
}

@end

In my application I have to do a lot of things like

Article *article= [objectsArray getObjectAtIndex:x];
NSString *title=article.title;
UILabel.text=title;
[title release];

I know I'm supposed to call retain when I get the property:

NSString *title=[article.title retain];

Maybe I am lazy to do a retain where I get the propery. Or If I need to do that tens of times all over the applicaiton.

Can I have getter to return a copy?

- (NSString *)title {
    return [title copy];
}
+1  A: 

It's a good idea to return a copy of mutable properties so other objects can't change your object out from under you.

In the case of a plain NSString, since it is immutable, both copy and retain do the same thing — they retain the string and return it.

Chuck
I disagree, it is better to return an immutable reference (especially in libraries), so only clients who need to mutate pay the cost of copying. The overhead of always copying may be prohibitive in some contexts.
notnoop
@msaeed: I'm not sure what you mean by an "immutable reference." I don't think Objective-C has any such construct. As I said, there is no "cost of copying" if the value is already immutable, which is the one case where it would be a waste.
Chuck
+5  A: 

There are some circumstances where I prefer to return a copy of the property for safety reasons. For example, if I'm writing a class that has a unique identifier property, then I'll "return [[_uniqueID copy] autorelease]" so that there's no chance that another class could do anything to the unique identifier. Other times I'll just return the object itself, because it's not a big deal if it's externally manipulated.

Also, with respect to these getter methods, they should not return objects with a +1 retain count (which is what you have going). If anything, they should return the object directly or return it with a +0 retain count (retain/copy + autorelease). It greatly simplifies your memory management to do it that way. If the external object needs to hold on to the returned object, then the external object should be responsible for retaining whatever it needs.

Dave DeLong
+1  A: 

On Chuck's note, you'll often see (NSMutableString *) properties return a copy of the object, rather than a reference to the original string. Like he points out, this is a safety mechanism, allowing you to deal with a "snapshot" of the string at the time it is accessed.

In your particular example, however, it looks like the title property is set once and then accessed to be used as text in a UILabel.

If this is your only application, you technically don't have to retain the NSString when you get it from the accessor.

NSString * articleTitle = article.title;
label.text = articleTitle;
articleTitle = nil;

The UILabel will store a retained copy of the string when its 'text' property is set. You can 'nil' the reference after setting the text, and you'll get the same result. No extra retain/release involved. (Although it may be good practice)

thauburger