This is a bit of a silly question, but if I want to add an object to an array I can do it with both NSMutableArray
and NSArray
, which should I use?
Use NSMutableArray, that is what it is there for. If I was looking at code and I saw NSArray I would expect it's collection to stay constant forever, whereas if I see NSMuteableArray I know that the collection is destined to change.
It might not sound like much right now, but as your project grows and as you spend more time on it you will see the value of this eventually.
Even the Q and the answer are very old, someone has to correct it.
If you are talking about performance, you can measure it yourself. But remember Donald Knuth: "Premature optimization is the root of all evil".
On an architectural point of view, things become more complicated.
First of all I have to mention, that having an instance of NSArray
does not mean, that it is immutable. This is, because in Cocoa the mutable variants of collections are subclasses of the immutable variants. Therefore an instance of NSMutableArray
is an instance of NSArray
, but obviously mutable.
One can say that this was no good idea, especially when thinking about Barbara and Jeanette and there is a relation to the circle-ellipse problem, which is not easy to solve. However, it is as it is.
So only the docs can give you the information, whether a returned instance is immutable or not. Or you do a runtime check. For this reason, some people always do a -copy
on every mutable collection.
However, mutability is another root of all evil. Therefore: If it is possible, always create an instance of NSArray
as final result. Write that in your docs, if you return that instance from a method (esp. getter) or not, so everyone can rely on immutability or not. This prevents unexpected changes "behind the scene". This is important, not 0.000000000003 sec runtime or 130 bytes of memory.
When deciding which is best to use:
NSMutableArray
is primarily used for when you are building collections and you want to modify them. Think of it as dynamic.
NSArray
is used for read only inform and either:
What you are actually doing here:
NSArray * array2;
array2 = [array2 arrayByAddingObject:obj];
is you are creating a new NSArray
and changing the pointer to the location of the new array you created.
You are leaking memory this way, because it is not cleaning up the old Array before you add a new object.
if you still want to do this you will need to clean up like the following:
NSArray *oldArray;
NSArray *newArray;
newArray = [oldArray arrayByAddingObject:obj];
[oldArray release];
But the best practice is to do the following:
NSMutableArray *mutableArray;
// Initialisation etc
[mutableArray addObject:obj];
An NSArray object manages an immutable array—that is, after you have created the array, you cannot add, remove, or replace objects. You can, however, modify individual elements themselves (if they support modification). The mutability of the collection does not affect the mutability of the objects inside the collection. You should use an immutable array if the array rarely changes, or changes wholesale.
An NSMutableArray object manages a mutable array, which allows the addition and deletion of entries, allocating memory as needed. For example, given an NSMutableArray object that contains just a single dog object, you can add another dog, or a cat, or any other object. You can also, as with an NSArray object, change the dog’s name—and in general, anything that you can do with an NSArray object you can do with an NSMutableArray object. You should use a mutable array if the array changes incrementally or is very large—as large collections take more time to initialize.
This test gives the best answer:
Method 1:
NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
NSMutableArray *mutableItems = [[NSMutableArray alloc] initWithCapacity:1000];
for (int i = 0; i < 10000; i++) {
[mutableItems addObject:[NSDate date]];
}
NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate];
NSLog(@"elapsed time = %g", (end - start) * 1000.0);
Method 2:
...
NSArray *items = [[[NSArray alloc] init] autorelease];
or (int i = 0; i < 10000; i++) {
items = [items arrayByAddingObject:[NSDate date]];
}
...
Output:
Method 1: elapsed time = 0.011135 seconds.
Method 2: elapsed time = 9.712520 seconds.
NSMutableArray
is not threadsafe, while NSArray
is. This could be a huge problem if you're multithreading.
NSMutableArray
and NSArray
both are build on CFArray
, performance/complexity should be same. The access time for a value in the array is guaranteed to be at
worst O(lg N) for any implementation, current and future, but will
often be O(1) (constant time). Linear search operations similarly
have a worst case complexity of O(N*lg N), though typically the
bounds will be tighter, and so on. Insertion or deletion operations
will typically be linear in the number of values in the array, but
may be O(N*lg N) clearly in the worst case in some implementations.