js_
js_

Reputation: 4731

Is it good practice to convert return value type from NSMutableArray to NSArray if return type of method is NSArray?

In the following code, I don't get any warning or compile error if I return NSMutableArray instead of NSArray which is the method's return type.

But is it good practice to convert return value to NSArray by using -copy method like the following code?
Or should I return NSMutableArray?

+(NSArray *)returnImutableArray {
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    [arr addObject:@"a"];
    [arr addObject:@"b"];

    //return arr; // no warning
    return [arr copy];
}

Upvotes: 2

Views: 481

Answers (3)

justin
justin

Reputation: 104698

I return an immutable copy of interior mutable instances by default. Not just NSArray, but several other types.

I don't want mutable objects floating around, although it's not a problem that it mutates as long as you treat it as concrete.

I consider it a better default because it minimizes shallow copying if shared. That is, if you take the result and assign it to one or more objects which are copy properties, then all those actions must make concrete shallow copies, when they could effectively retain. This is the same reason you should favor copy for properties of these types, rather than retain when declaring properties.

In some cases, you just know its scope is limited and that the mutable won't get out -- in that case, I may not bother making the copy.

Upvotes: 0

flovilmart
flovilmart

Reputation: 1769

This all depends on what you want to achieve with the array.

If you really don't want or need to modify the returned array, return it as an NSArray. You could as well return it as an array, without copying it.

In both cases, don't forget the memory management.

You should never return anything with a retain count >0.

+(NSArray *)returnImutableArray {
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    [arr addObject:@"a"];
    [arr addObject:@"b"];

    NSArray * returnArray = [NSArray arrayWithArray:arr];
    [arr release];
    //return arr; // no warning
    return returnArray;
}

Or you could do so:

+(NSArray *)returnImutableArray {
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    [arr addObject:@"a"];
    [arr addObject:@"b"];
    //return arr; // no warning
    return [arr autorelease];
}

There's no need to copy the NSMutableArray as it extends the NSArray so your code will never break if you do so.

Upvotes: 0

Andrew Madsen
Andrew Madsen

Reputation: 21373

I think this is essentially personal preference. You incur a (probably small) performance penalty by copying the array before returning it. The upside is that you'll completely prevent mutation of the result further down the line. However, I don't usually go to the trouble. Because the declared return type of the method is an immutable NSArray, the compiler will warn you if you try to call one of NSMutableArray's mutation methods on it unless you go out of your way to prevent that (by casting to NSMutableArray).

So, in short, it's personal preference and I personally don't generally bother with the immutable copy.

Upvotes: 6

Related Questions