2010-11-27 18 views
0

Meine App lädt Bilder von einer URL in einer bestimmten Reihenfolge herunter und der Benutzer sieht sie. Ich lasse die App das nächste Bild vorladen und die älteren Bilder in einem Cache behalten.Speicher wird nicht korrekt freigegeben?

Dieser Cache ist im Grunde ein NSMutableDictionary mit Schlüsseln, die der Image-ID zugeordnet sind. Jedes Objekt im Cache ist auch ein NSDictionary mit der URL, der Image-URL, einem Titel und einem NSData-Objekt. Wenn ich das Bild herunterlade, füge ich ein neues Wörterbuchobjekt mit diesen Elementen in den Cache ein. Ich speichere das NSData-Objekt wie folgt: NSData * imgData = [[NSData-Alloc] initWithContentsOfURL: [NSURL URLWithString: Bildurl]]; Ich füge dieses Objekt dann dem Child-Dictionary-Objekt hinzu.

Dies nimmt offensichtlich eine große Menge an RAM nach einer großen Anzahl von Fotos gespeichert und zwischengespeichert, so dass ich die Speicherwarnung durch Löschen des gesamten Caches reagieren. Das Problem ist, egal was ich versucht habe, ist kein RAM freigegeben. Die Objekte verschwinden (wie sie sollten), geben aber kein RAM zurück. Ich habe versucht, Folgendes zu tun:

  • Schleifen durch das Cache-Verzeichnis, die Freigabe des Datenobjekts im Kind-Wörterbuch, dann, wenn alle Elemente durchlaufen werden, entfernen Sie alle Cache-Wörterbuch Kind Objekte.
  • Looping durch den Cache-Wörterbuch, die Freigabe des Kind-Wörterbuch, das Entfernen aller Objekte, wenn
  • fertig
  • Auch alle Objekte zu entfernen, dann das gesamte Cache-Objekts Freigabe (dann neu zu erstellen, weil es immer noch verwendet werden muss)
  • Und andere zufällige Combos des Freigebens, des Entfernens usw.
  • Das Problem ist, NICHTS, das ich versucht habe, hat RAM befreit. Gibt es etwas, was ich falsch mache, wenn ich den Speicher der NSData-Objekte freigebe?

    +0

    Welche Cache-Richtlinie verwenden Sie beim Herunterladen der Daten? Haben Sie bestätigt (d. H. Mit Leaks oder Zuordnungen), dass die Erinnerung definitiv durchgesickert oder aufgegeben wird? –

    +0

    Ich verwende kein Caching, das in das iOS SDK integriert ist. Ich verwalte mein eigenes mit einem NSDictionary, das mit NSData-Objekten gefüllt ist (die die Bilder enthalten). Wenn ich alle Objekte aus dem Wörterbuch lösche, wird kein Speicher freigegeben. Ich bin mir nicht sicher, wo genau dieser Speicher noch zugewiesen wird, aber es wird nicht freigelassen, wie ich es möchte. –

    Antwort

    1

    Die Funktionsweise des Speichermanagements in Objective-C besteht darin, dass Sie das Eigentum an einem Objekt durch Zuweisen/Angeben, Zurückgeben oder Kopieren übernehmen, und Sie es ablehnen, wenn Sie es nicht über -release oder -autorelease benötigen.

    Was Sie tun möchten, ist:

    1) Erstellen Sie das Datenobjekt

    NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]]; 
    

    Sie besitzen nun die Objekt imgData Punkte.

    2) hinzufügen, das Objekt zu Ihrem Kind Wörterbuch

    [childDictionary setObject:imgData forKey:@"imgData"]; 
    

    3) Schließen Sie das Datenobjekt. Du brauchst es nicht mehr. childDictionary benötigt es, aber das ist nicht dein Problem. childDictionary ist wie jedes andere Objekt für die Verwaltung seines eigenen Speichers und seiner Eigentümer zuständig.

    [imgData release]; 
    

    Eine andere Möglichkeit, die Sie tun können, ist eine Autoreleased Version des Datenobjekts erstellen, und die in die Dictioary hinzuzufügen.

    Als nächstes müssen Sie sicherstellen, dass Sie Speicher verwalten, sowie cache Speicher ordnungsgemäß. Erstellen

    1) eine Autoreleased childDictionary

    NSMutableDictionary *childDictionary = [NSMutableDictionary dictionary]; 
    

    2) In Sachen childDictionary (wie wir zuvor)

    3) In childDictionary in den Cache

    [cache setObject:childDictionary forKey:yourKey]; 
    

    : Zum Beispiel 4) Da childDictionary automatisch freigegeben wurde, müssen Sie es jetzt nicht mehr freigeben (und sollten es auch nicht), da Sie es nicht benötigen. Es wird zu einem späteren Zeitpunkt automatisch vom Hauptpool für die automatische Freigabe freigegeben. Wenn Sie Ihren childDictionary erstellt hatte mit:

    NSMutableDictionary *childDictionary = [[NSMutableDictionary alloc] init]; 
    

    , die ein Objekt mit einem retainCount von 1 zurückkehrt, dann hätte man brauchte Eigentum zu entlassen jetzt:

    [childDictionary release]; 
    

    Soweit Cache geht, haben Sie wahrscheinlich Ich möchte das für eine lange Zeit beibehalten: Es ist höchstwahrscheinlich eine Instanzvariable von jedem Objekt, das den Cache verwaltet, und es wird mit [cache removeAllObjects] zurückgesetzt, wenn Sie die Speicherwarnung drücken.

    Wenn Sie auf dem Mac mit Garbage Collection entwickeln, ist all dies nutzlos. Aber seit Sie telefonieren, müssen Sie diese einfachen Regeln zur Speicherverwaltung kennen. Meine Erklärung übersieht wirklich viele der Konzepte, mit denen Sie vertraut sein sollten, also ermutige ich Sie, the Apple documentation about this zu lesen.

    0

    Ein vereinfachtes Codebeispiel, das dieses Leck veranschaulicht, wäre hilfreich. Kann es sein, dass der Aufruf, den Sie verwenden, um imgData dem Wörterbuch hinzuzufügen, nur von Ihrer Beschreibung beibehalten wird? Wenn Sie imgData nicht sofort in Ihrem eigenen Code freigeben, haben Sie eine Retain-Anzahl von 2. Wenn Ihr lokaler imgData-Pointer den Gültigkeitsbereich verlässt, haben Sie den Speicher verloren. Dies ist jedoch nur ein Stich im Dunkeln ohne ein Codebeispiel.

    Verwandte Themen