你有几个选择:
选项 1: 用 NSNull 的实例预先填充数组,然后使用 Dave DeLong 在 his answer 中给出的代码。
选项 2:(类似于 #1)用 NSMutableArray 的实例预先填充数组,然后根本没有额外的代码。 (如果你要预填,你也可以这样做)。
选项3:不要预先填充数组,而是根据需要动态插入项目。如果第一个 iLine 接近最大值,这将与预填充几乎相同:
while([arrAllBlocks count] <= iLine)
{
[arrAllBlocks addObject:[NSMutableArray arrayWithCapacity:0]];
}
NSMutableArray *columArray = (NSMutableArray *)[arrAllBlocks
objectAtIndex:iLine];
[columArray insertObject:newBlock atIndex:iColumn];
选项4:使用字典来维护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];
如何选择:
如果iLine 的最大值不是很大,我会选择选项#2。少数NSMutableArrays 初始化为零容量将占用很少的内存。
如果iLine 的最大值很大,但您希望它被稀疏访问(即,只有少数iLine 的值会被访问),那么您应该使用选项#4。这将使您不必用从未使用过的对象填充NSMutableArray。转换字典的字符串值键的开销将小于创建所有这些空白的开销。
如果您不确定,请尝试每个选项并分析它们:测量您的内存使用情况和执行所需的时间。如果这些选项都不起作用,您可能需要探索更复杂的解决方案,但只有在必要时才这样做。
注意事项:
您发布的原始代码在以下行中存在内存泄漏:
[arrAllBlocks insertObject:[[NSMutableArray alloc] init] atIndex:iLine];
您在此处初始化的NSMutableArray 对象永远不会被释放。当您调用 [[NSMutableArray init] alloc] 时,会创建一个全新的对象(引用计数为 1)。然后insertObject 方法将该新对象添加到arrAllBlocks 和retains 它(将其保留计数增加到2)。稍后,当您释放arrAllBlocks 时,新数组将发送release 消息,但这只会将其保留计数再次减少到一个。那时,它会一直停留在 RAM 中,直到您的程序退出。
这里最好使用[NSMutableArray arrayWithCapacity:0] 代替(正如我在示例中所做的那样)。这将返回一个新的NSMutableArray,与您的代码一样,但该实例已经是autoreleased。这样,arrAllBlocks 可以取得新对象的所有权,并且您可以确定它会在适当的时候被释放。