You have a few options here:
Option 1: Pre-fill the array with instances of NSNull
, and then use the code given by Dave DeLong in his answer.
Option 2: (Similar to #1) pre-fill the array with instances of NSMutableArray
, and then have no extra code at all. (If you're going to pre-fill, you may as well do this).
Option 3: Do not pre-fill the array, but insert items dynamically as required. This will be almost identical to a pre-fill if the first iLine
is near the maximum:
while([arrAllBlocks count] <= iLine)
{
[arrAllBlocks addObject:[NSMutableArray arrayWithCapacity:0]];
}
NSMutableArray *columArray = (NSMutableArray *)[arrAllBlocks
objectAtIndex:iLine];
[columArray insertObject:newBlock atIndex:iColumn];
Option 4: Use a dictionary to maintain the list of NSMutableArrays
:
NSString *key = [NSString stringWithFormat:@"%d", iLine];
NSMutableArray *columnArray = [dictAllBlocks objectForKey:key];
if (columnArray == nil)
{
columnArray = [NSMutableArray arrayWithCapacity:0];
[dictAllBlocks setObject:columnArray forKey:key];
}
[columArray insertObject:newBlock atIndex:iColumn];
How to choose:
If the maximum value for iLine
is not enormous, I would go with option #2. A handful of NSMutableArrays
initialized to zero capacity will take up very little memory.
If the maximum value for iLine
is enormous, but you expect it to be accessed sparsely (i.e., only a few values of iLine
will ever be accessed), then you should go with Option #4. This will save you from having to fill an NSMutableArray
with objects that never get used. The overhead of converting the string-value key for the dictionary will be less than the overhead for creating all of those blanks.
If you're not sure, try out each option and profile them: measure your memory usage and the time required to execute. If neither of these options work, you may have to explore more complex solutions, but only do that if it turns out to be necessary.
A note of caution:
The original code that you posted has a memory leak in the following line:
[arrAllBlocks insertObject:[[NSMutableArray alloc] init] atIndex:iLine];
The NSMutableArray
objects that you initialize here are never released. When you call [[NSMutableArray init] alloc]
, a brand new object is created (with a reference count of one). The insertObject
method then adds that new object to arrAllBlocks
, and retains
it (increasing its retain count to 2). Later, when you release arrAllBlocks
, the new array will be sent a release
message, but that will only reduce its retain count to one again. At that point, it will stick around in RAM until your program exits.
The best thing to do here is to use [NSMutableArray arrayWithCapacity:0]
instead (as I have done in my examples). This returns a new NSMutableArray
, just the same as your code did, but this instance has already been autoreleased
. That way, arrAllBlocks
can take ownership of the new object and you can be sure that it will be released when appropriate.