Vermeidung von registrierten Objektanhäufungen (Memleak) in NSManagedObjectContext

8

Ich habe eine speicherintensive iOS-App und arbeite daran, sicherzustellen, dass die Speichernutzung nicht im Laufe der Zeit zunimmt. Meine App hat einen "Haupt" -Kontext, der für die gesamte Lebensdauer der App existiert, während andere kleinere Kontexte gelegentlich für Hintergrundaufgaben erzeugt werden.

Eine Sache, die ich bemerkt habe, ist, dass NSManagedObjects langfristig im Hauptkontext registriert zu bleiben scheint und die einzige Möglichkeit, den gesamten mit dem Ziehen der Objekte aus der Datenbank verbundenen Speicher wiederzuerlangen, lautet [NSManagedObjectContext reset] .

Dies führt natürlich zu einem schönen Rückgang der Speicherauslastung, da alle registrierten Objekte aus kürzlich geschlossenen Listenansichten ordnungsgemäß aus dem Speicher ausgeworfen werden. Dies ist jedoch ärgerlich, da Sie gerade jedes in diesem Kontext registrierte Objekt für ungültig erklärt haben einen Verweis auf (dh Objekte, auf die noch offene Sichten verweisen), und Sie müssen nun alle diese Objekte aus der Datenbank abrufen, um Ausnahmen für den Zugriff auf ein ungültiges Objekt zu vermeiden.

Ist dies die einzige Möglichkeit, den registrierten Objektsatz aus einem NSManagedObjectContext auszulöschen, oder gibt es einen besseren Weg, alle registrierten Objekte, auf die Sie keine Verweise mehr haben, erfolgreich auszuwerfen, aber nicht alle NSManagedObjects, die still sind lebendig?

    
glenc 21.06.2011, 20:44
quelle

1 Antwort

12

NSManagedObjectContext hat einen internen Zeilencache, und die einzige Möglichkeit, dies zu beseitigen, ist das Zurücksetzen des Kontexts. Wenn Sie tatsächlich Probleme mit dem Arbeitsspeicher haben, helfen Ihnen einige Dinge:

  • Verwaltete Objekte behalten ihre zugehörigen Objekte bei. Wenn Sie das Objekt A verwaltet haben, auf das eine Beziehung von einem anderen verwalteten Objekt B verweist, bleibt das Objekt A im Speicher, auch wenn Sie alle Verweise darauf freigegeben haben. Es wird nicht wirklich freigegeben, bis das Objekt B freigegeben oder neu fehlerhaft ist, weil es von B beibehalten wird.
  • Eine Möglichkeit, dies (und andere Speicherprobleme) zu behandeln, besteht darin, refreshObject:mergeChanges: für Objekte, die Sie gerade nicht verwenden, auf dem MOC aufzurufen, wobei das zweite Argument auf NO gesetzt ist. Dies führt zu einer erneuten Fehlerhaftigkeit des Objekts, d. H. Es bringt das Objekt in den ursprünglichen "Fehler" -Zustand zurück und entlädt seine Eigenschaftswerte und Beziehungen. Mit A und B von vorher würde das erneute Verschulden von B die Beziehung zu A freigeben. Beachten Sie, dass dadurch nicht gespeicherte Änderungen an B verloren gehen. Stellen Sie daher sicher, dass Sie bei Bedarf zuerst gespeichert haben.
  • Wenn Ihre verwalteten Objekte irgendwelche großen binären Daten enthalten, verschieben Sie diese Daten in eine separate Entität oder aus Core Data, damit sie nicht in den Speicher geladen wird, wenn sie nicht benötigt wird.
  • reset auf dem MOC ist im Grunde die nukleare Option, wenn es um Kerndatenspeicherverwaltung geht. Es ist extrem effektiv, aber wie Sie gefunden haben, kann sehr gefährlich sein. Es wird am besten vermieden, es sei denn, Sie verwenden bereits keine Objekte, die vom MOC geladen wurden.
Tom Harrington 23.06.2011 23:33
quelle