inessential by Brent Simmons

Follow up to memory management thing

In the previous post I have an initWithString method that looks like this:

- (id)initWithString:(NSString *)aString {
    self = [super init];
    if (self == nil)
        return nil;
    something = [aString retain];
    return self;
}

I knew, as I was typing it, that I’d get some feedback along the lines that I should use copy instead of retain.

And I did.

And it’s excellent advice, totally, no question. The reason to use copy instead of retain is because it enforces the expected immutability of that incoming string, so the caller is free to change it in case it’s really a mutable string.

However, I don’t follow that advice. One reason is that, in my eight years of Cocoa programming, this has never been an issue. Not once have I run into a problem because I used retain instead of copy in a case like this.

The second reason is that I consider the use of copy here a case of overly-defensive programming. The effect would be to hide a bug, if one exists, and I wouldn’t want that.

Given those two reasons, it’s just bonus that using retain means avoiding the extra allocation that using copy would mean — but I’ll take that bonus.

Update 5:24 pm: Yes, copy returns self for immutable objects. (All the time, at least for Foundation objects? I don’t know.) So, no bonus in those cases. But I myself often pass mutable objects where immutable is expected. So I get the bonus. (And it’s not a bug on my part, no.)

Update 5:41 pm: OK, why do I consider it a bug if aString is really a mutable string and I change it elsewhere? It’s totally legal if aString is really an NSMutableString. I do things like that all the time. But I code as if there’s an implicit contract: any Foundation objects (strings, dictionaries, arrays, sets, etc.) passed between objects must be treated as if immutable. If the object that receives the object wants to do something based on aString, it may, indeed, then have to make a mutableCopy or whatever. And if aString was really a mutable string, the caller has to not change it from that point on.

Why do I code this way? It simplifies things. It removes doubt.