15

I have a for loop. Inside that loop I want to fill up an NSArray with some objects. But I don't see any method that would let me do that. I know in advance how many objects there are. I want to avoid an NSMutableArray, since some people told me that's a very big overhead and performance-brake compared to NSArray.

I've got something like this:

NSArray *returnArray = [[NSArray alloc] init];
for (imageName in imageArray) {
    UIImage *image = [UIImage imageNamed:imageName];
    //Now, here I'd like to add that image to the array...
}

I looked in the documentation for NSArray, but how do I specify how many elements are going to be in there? Or must I really use NSMutableArray for that?

Venk
  • 5,949
  • 9
  • 41
  • 52
Thanks
  • 40,109
  • 71
  • 208
  • 322
  • I haven't got time to look this up right now, but perhaps you need to create an NSMutableArray first, and then use a method on that to get the Immutable version? Not sure if that simply would give you an Immutable interface and no speed gain (i.e. it might be same underlying implementation as mutable), but worth a look. As far as I remember the Apple docs are clear as mud on this. – frankodwyer May 08 '09 at 12:41
  • 5
    Don't listen to people who tell you that something has bad performance! NSMutableArray is a core part of Objective-C, it is highly optimised, and there is no reason to avoid it! – Jakob Egger Oct 23 '11 at 12:50

4 Answers4

27

Yes, you need to use an NSMutableArray:

int count = [imageArray count];
NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:count];
for (imageName in imageArray) {
    UIImage *image = [UIImage imageNamed:imageName];
    [returnArray addObject: image];
    ...
}

EDIT - declaration fixed

Venk
  • 5,949
  • 9
  • 41
  • 52
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Thanks. Are you sure that the data structure of the variable is of type NSArray, and not NSMutableArray? Or are those interchangeable? – Thanks May 08 '09 at 12:43
  • NSMutableArray is a subclass of NSArray, so it's safe. – Alnitak May 08 '09 at 12:48
  • Yeah, I forgot. Thanks! That raises another question ;) – Thanks May 08 '09 at 12:50
  • Since it's being used as a mutable array, returnArray should be declared as an NSMutableArray. This code will work since the object really is the mutable variety, but it's bad practice (and will give a warning about NSArray not responding to addObject:). – smorgan May 08 '09 at 13:24
  • So if that's bad practice, of course I'll do NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:count]; ;) – Thanks May 08 '09 at 16:08
4

You'll need to use an NSMutableArray for that because adding is mutation and NSArray is immutable.

You could make a populated NSMutableArray into an NSArray afterwards (see here for a discussion) but you won't be adding items to a regular old NSArray anytime soon.

Venk
  • 5,949
  • 9
  • 41
  • 52
Kris
  • 40,604
  • 9
  • 72
  • 101
3

Would this be a good time to use an NSMutableArray?

I know you mentioned that you would like to avoid it, but sometimes there's a reason for things like this.

Wally Lawless
  • 7,539
  • 7
  • 37
  • 53
2

I would advise optimising only when you know NSMutableArray is causing you a performance hit but if it is, you can always create a static aray from a mutable array after you have populated it. It depends on if the performance hit is caused by you subsequent use of the NSMutableArray or just by creating it.

My guess is that this isn't going to be the performance bottleneck on your app.

Venk
  • 5,949
  • 9
  • 41
  • 52
Rog
  • 17,070
  • 9
  • 50
  • 73