Sie ein paar Optionen hier:
Option 1: vorfüllen das Array mit Instanzen von , und verwenden Sie dann den von Dave DeLong in his answer angegebenen Code.
Option 2: (Ähnlich wie # 1) füllen Sie das Array mit Instanzen von NSMutableArray
, und haben dann keinen zusätzlichen Code. (Wenn Sie vorfüllen möchten, können Sie dies auch tun).
Option 3: Füllen Sie das Array nicht vorab, sondern fügen Sie Elemente dynamisch nach Bedarf ein. Dies wird fast identisch mit einem vorab füllen, wenn die erste iLine
nahe dem Maximum ist:
while([arrAllBlocks count] <= iLine)
{
[arrAllBlocks addObject:[NSMutableArray arrayWithCapacity:0]];
}
NSMutableArray *columArray = (NSMutableArray *)[arrAllBlocks
objectAtIndex:iLine];
[columArray insertObject:newBlock atIndex:iColumn];
Option 4:
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];
Wie: Verwenden Sie ein Wörterbuch, um die Liste der NSMutableArrays
zu halten zu wählen:
Wenn der Höchstwert für iLine
nicht enorm ist, würde ich mit Option # 2 gehen. Eine Handvoll NSMutableArrays
initialisiert auf Null Kapazität wird sehr wenig Speicher aufnehmen.
Wenn der Höchstwert für iLine
enorm ist, aber Sie erwarten, dass er nur spärlich aufgerufen wird (d. H., Nur wenige Werte von iLine
werden jemals aufgerufen), sollten Sie Option 4 wählen. Dadurch ersparen Sie es sich, einen NSMutableArray
mit Objekten zu füllen, die niemals benutzt werden. Der Aufwand zum Konvertieren des Zeichenfolgenwertsschlüssels für das Wörterbuch ist geringer als der Aufwand zum Erstellen all dieser Leerzeichen.
Wenn Sie nicht sicher sind, probieren Sie jede Option aus und profilieren Sie sie: messen Sie die Speicherauslastung und die Ausführungszeit. Wenn keine dieser Optionen funktioniert, müssen Sie möglicherweise komplexere Lösungen untersuchen, aber nur, wenn es sich als notwendig erweist.
Ein Wort der Warnung:
Der ursprüngliche Code, den Sie ein Speicherleck in der folgenden Zeile geschrieben hat:
[arrAllBlocks insertObject:[[NSMutableArray alloc] init] atIndex:iLine];
Die NSMutableArray
Objekte, die Sie hier initialisieren nie veröffentlicht. Wenn Sie [[NSMutableArray init] alloc]
aufrufen, wird ein brandneues Objekt erstellt (mit einer Referenzzahl von eins). Die insertObject
Methode fügt dann das neue Objekt zu arrAllBlocks
und retains
es (Erhöhung seiner Retain-Anzahl auf 2). Später, wenn Sie arrAllBlocks
freigeben, wird das neue Array eine release
Nachricht gesendet, aber das wird nur seine Retain-Anzahl auf eins wieder reduzieren. An diesem Punkt wird es im RAM bleiben, bis Ihr Programm beendet wird.
Das beste, was Sie hier tun können, ist stattdessen [NSMutableArray arrayWithCapacity:0]
zu verwenden (wie ich in meinen Beispielen getan habe). Dies gibt eine neue NSMutableArray
zurück, genauso wie Ihr Code, aber diese Instanz wurde bereits autoreleased
. Auf diese Weise kann arrAllBlocks
Besitz des neuen Objekts übernehmen und Sie können sicher sein, dass es bei Bedarf freigegeben wird.
Hummm, ok! Aber ich versuche, was Sie sagen, und noch nicht arbeiten =/ Ich brauche das, becouse die Anzahl der Objekte in arrAllBlocks, kann sich ändern! Also möchte ich diese Dynamik machen! Ich kann dafür sorgen, dass alle Instanzen erstellt werden, die ich brauche, aber es sieht ein wenig Hardcode aus! – baDa
@Dave DeLong: Sie haben recht mit der Verwendung von NSNull-Objekten, aber baDa müsste sein Array mit ihnen vorher füllen, damit dies funktioniert. Wenn er das macht, kann er das Array genauso gut mit leeren NSMutableArrays füllen. Ich habe eine Antwort mit mehr Details gepostet. –
@eJames: guter Punkt, und gute Antwort (ich habe es gewählt). NSNull wäre für den Fall, wenn er Indizes beibehalten möchte, aber immer noch bestimmte Positionen innerhalb seines Arrays "nil". =) –