I need to check specific positions in an NSArray to see if they have already been initialized, but I am having trouble. I tried to do the following, but it causes my application to crash!
if ((NSMutableArray *)[arrAllBlocks objectAtIndex:iLine] == nil)
{
[arrAllBlocks insertObject:[[NSMutableArray alloc] init] atIndex:iLine];
}
NSMutableArray *columArray = (NSMutableArray *)[arrAllBlocks
objectAtIndex:iLine];
[columArray insertObject:newBlock atIndex:iColumn];
What is the best to do this? I already tried some methods like isValid, and things like that!
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
iLineis near the maximum:Option 4: Use a dictionary to maintain the list of
NSMutableArrays:How to choose:
If the maximum value for
iLineis not enormous, I would go with option #2. A handful ofNSMutableArraysinitialized to zero capacity will take up very little memory.If the maximum value for
iLineis enormous, but you expect it to be accessed sparsely (i.e., only a few values ofiLinewill ever be accessed), then you should go with Option #4. This will save you from having to fill anNSMutableArraywith 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:
The
NSMutableArrayobjects 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). TheinsertObjectmethod then adds that new object toarrAllBlocks, andretainsit (increasing its retain count to 2). Later, when you releasearrAllBlocks, the new array will be sent areleasemessage, 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 newNSMutableArray, just the same as your code did, but this instance has already beenautoreleased. That way,arrAllBlockscan take ownership of the new object and you can be sure that it will be released when appropriate.