tags:

views:

46

answers:

1

Ok, so I have a method that takes an NSString as input, does an operation on the contents of this string, and returns the processed string. So the declaration is:

- (NSString *) processString: (NSString *) str;

The question: should I just return the NSMutableString instance that I used as my "work" buffer, or should I create a new NSString around the mutable one, and return that?

So should I do this:

- (NSString *) processString: (NSString *) str
{
    NSMutableString *work = [NSMutableString stringWithString: str];
    // process 'work'
    return work;
}

Or this:

- (NSString *) processString: (NSString *) str
{
    NSMutableString *work = [NSMutableString stringWithString: str];
    // process 'work'
    return [NSString stringWithString: work]; // or [work stringValue]?
}

The second one makes another copy of the string I'm returning, unless NSString does smart things like copy-on-modify. But the first one is returning something the caller could, in theory, go and modify later. I don't care if they do that, since the string is theirs. But are there valid reasons for preferring the latter form over the former? And, is either stringWithString or stringValue preferred over the other?

+3  A: 

Depends entirely on how defensive you need to be.

There is no reasonable way a client of your code can test for mutability. Thus, there is no reasonable way that a client can cast from NSString to NSMutableString and suddenly achieve no-compiler-warning mutability of the string.

So, as long as you trust your clients, you might as well return the mutable string (as an NSString). Even if the client does something stupid and mutates it, compiler warnings be damned, nothing breaks.

Where it does matter is when you are returning the mutable backing store of some object that should not be mutated externally. In that case, the client might ignore the compiler warnings and/or cast to the mutable variant and completely bork your object.

Or, more subtly, the client might grab a reference to the supposedly immutable return type and hold onto it long enough that it is mutated later, leaving their reference in a surprising state.

Best practice: When computing and returning a transient value, mutability is irrelevant. When returning a reference to an internal mutable store, best to make an immutable copy.

bbum