Hi,
ich hatte heute einen interessaten Fall, wo man tatsächlich trotz ARC noch selber einen AP braucht. Dabei war das gar nicht mal so ein exotischer Anwendungsfall und eventuell gilft es dem einen oder anderen Anfänger zu wissen was man machen muss wenn man in so eine Situation kommt:
Es ging darum, aus einem Template-String einen XML-String zu erzeugen. Im Template stehen Placeholder ala @@@@@WasWeißIch@@@@@ und diese werden dann durch die Werte aus den Objekten ersetzt. Ich hatte nun ca. 400 Objecte mit je ca. 20 Attributen, was bei meinem ursprünglichen Code zu einem Speicherverbrauch von über 80MB geführt hat und damit meine App auf einem alten iPad zum Absturz brachte.
Im Code sah das dann so aus:
Alles anzeigen
Was hier nun passiert ist eigentlich klar. Es wird rund 400*20 mal ein alter String durch einen neuen ersetzt. Damit verliert man die Referenz auf den alten String und denkt sich "Ok das räumt ARC auf". Stimmt ja auch. Doch dummerweise kommt ARC innerhalb der Schleife überhaupt nicht zum Zuge. Der AutoreleasePool wird nämlich erst frühestens nach dem Verlassen der Methode aufgerufen in der diese Schleife steht. Somit wird schön brav der Speicher verbraten, bis die App letztendlich vom System verwarnt wird und dann abgeschossen...
Abhilfe schafft in diesem Fall ein eigener AutoreleasePool innerhalb der Schleife. Also ganz einfach
Alles anzeigen
Nun werden nach jedem Schleifendurchlauf die alten Strings freigegeben und man benötigt nur noch 1/400 des Speichers.
Gruß
Claus
ich hatte heute einen interessaten Fall, wo man tatsächlich trotz ARC noch selber einen AP braucht. Dabei war das gar nicht mal so ein exotischer Anwendungsfall und eventuell gilft es dem einen oder anderen Anfänger zu wissen was man machen muss wenn man in so eine Situation kommt:
Es ging darum, aus einem Template-String einen XML-String zu erzeugen. Im Template stehen Placeholder ala @@@@@WasWeißIch@@@@@ und diese werden dann durch die Werte aus den Objekten ersetzt. Ich hatte nun ca. 400 Objecte mit je ca. 20 Attributen, was bei meinem ursprünglichen Code zu einem Speicherverbrauch von über 80MB geführt hat und damit meine App auf einem alten iPad zum Absturz brachte.
Im Code sah das dann so aus:
Quellcode
- NSString *xmlString=... <- hier wird der XML String intialisiert mit Header etc.
- for(MeinObject object in meineObjecte)
- {
- NSString *objectTemplate=[self getXMLFromRessource:RESSOURCE_TEMPLATE_SPEICHERE_BBFELD]; <- ist der TemplateString
- NSString *xmlObject=[xmlObject stringByReplacingOccurrencesOfString:PLACEHOLDER_VALUE1 withString:object.value1];
- xmlObject=[xmlObject stringByReplacingOccurrencesOfString:PLACEHOLDER_VALUE2 withString:object.value2];
- xmlObject=[xmlObject stringByReplacingOccurrencesOfString:PLACEHOLDER_VALUE3 withString:object.value3];
- ....
- xmlString=[xmlString stringByAppendigString:xmlObject];
- }
Was hier nun passiert ist eigentlich klar. Es wird rund 400*20 mal ein alter String durch einen neuen ersetzt. Damit verliert man die Referenz auf den alten String und denkt sich "Ok das räumt ARC auf". Stimmt ja auch. Doch dummerweise kommt ARC innerhalb der Schleife überhaupt nicht zum Zuge. Der AutoreleasePool wird nämlich erst frühestens nach dem Verlassen der Methode aufgerufen in der diese Schleife steht. Somit wird schön brav der Speicher verbraten, bis die App letztendlich vom System verwarnt wird und dann abgeschossen...
Abhilfe schafft in diesem Fall ein eigener AutoreleasePool innerhalb der Schleife. Also ganz einfach
Quellcode
- NSString *xmlString=... <- hier wird der XML String intialisiert mit Header etc.
- for(MeinObject object in meineObjecte)
- {
- @autoreleasepool
- {
- NSString *objectTemplate=[self getXMLFromRessource:RESSOURCE_TEMPLATE_SPEICHERE_BBFELD]; <- ist der TemplateString
- NSString *xmlObject=[xmlObject stringByReplacingOccurrencesOfString:PLACEHOLDER_VALUE1 withString:object.value1];
- xmlObject=[xmlObject stringByReplacingOccurrencesOfString:PLACEHOLDER_VALUE2 withString:object.value2];
- xmlObject=[xmlObject stringByReplacingOccurrencesOfString:PLACEHOLDER_VALUE3 withString:object.value3];
- ....
- xmlString=[xmlString stringByAppendigString:xmlObject];
- }
- }
Nun werden nach jedem Schleifendurchlauf die alten Strings freigegeben und man benötigt nur noch 1/400 des Speichers.
Gruß
Claus
2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.
Pre-Kaffee-Posts sind mit Vorsicht zu geniessen
Pre-Kaffee-Posts sind mit Vorsicht zu geniessen