In welcher Methode sollte ich Ressourcen nach didReceiveMemoryWarning neu erstellen?

8

Ich habe einen View-Controller, der eine private NSArray -Variable hat. Die Variable wird in der Methode viewDidLoad initialisiert. Für den Fall, dass didReceiveMemoryWarning aufgerufen wird, ergeben sich einige Fragen:

  1. Soll ich die private Variable auf nil setzen?
  2. Wenn ich es auf nil in welcher Methode muss es neu erstellt werden? Ruft der View-Controller die Methode viewDidLoad auf, um sie neu zu erstellen?

Ich frage, weil andere Methoden der Ansicht diese Variable benötigen und nicht funktionieren, wenn es nil ist.

Danke!

    
planewalker 31.05.2013, 10:01
quelle

5 Antworten

-2

Es ist besser, die Variable auf null zu setzen. Ich meine, geben Sie den Speicher frei, den es in didReceiveMemoryWarning hält, und setzen Sie ein schmutziges Flag.

Sie können immer das schmutzige Flag im Getter des Arrays überprüfen (Sie können Ihr eigenes schreiben) und es erneut füllen. Es ist wahrscheinlich nicht der beste Weg. Es hängt vollständig von der Verwendung des Arrays ab.

    
Vignesh 31.05.2013, 10:19
quelle
4

Normalerweise entladen Sie eine private Eigenschaft, indem Sie nil über den Setter zuweisen (z. B. self.propertyName = nil ). Oder Sie könnten den ivar nach dem Aufrufen der Freigabe auf Null setzen, z. [_propertyName release]; _propertyName = nil; , aber Ersteres ist vorzuziehen.

Die Methode didReceiveMemoryWarning wird aufgerufen, wenn eine Situation mit wenig Speicher vorliegt. Es wird auf jedem View-Controller aufgerufen, einschließlich derjenigen, die für die aktuell sichtbare Benutzeroberfläche verantwortlich sind!

Daher können Sie nicht einfach Daten beliebig entladen, wenn Sie einen Aufruf von didReceiveMemoryWarning erhalten - der View-Controller benötigt diese Daten möglicherweise, wenn er gerade auf dem Display angezeigt wird.

Das allgemeine Prinzip ist, dass didReceiveMemoryWarning alle Ressourcen, die es zur Verfügung stellen kann, loswerden kann, um Speicher freizugeben, aber nur diejenigen, die nicht sofort benötigt werden. In einem OpenGL-Spiel würden Sie beispielsweise keine Texturen entfernen, die derzeit auf dem Bildschirm angezeigt werden. Siehe jedoch meinen letzten Absatz.

Normalerweise laden Sie die Ressourcen neu, indem Sie prüfen, ob sie geladen sind, wenn Sie sie benötigen, und wenn nicht, laden Sie sie.

Es lohnt sich nicht, kleine Ressourcen wie eine einzelne normal große Zeichenfolge zu nieren / freizugeben. Sie sollten sich auf Dinge konzentrieren, die viel Speicher benötigen.

Aufgrund der jüngsten Fortschritte bei der Speicherverwaltung hinter den Kulissen ist es heutzutage weniger wahrscheinlich, dass Daten tatsächlich entladen werden müssen - das Betriebssystem kann unkomprimierte Bilddaten und dergleichen im Hintergrund löschen und neu laden.

Wie Hot Licks erwähnt hat der Simulator eine Option zum Simulieren einer Speicherwarnung. Es empfiehlt sich, diese Speicherwarnung an verschiedenen Punkten in Ihrer App auszulösen, um zu sehen, wie sie sich verhält.

    
occulus 31.05.2013 15:00
quelle
1

Erstellen Sie einen benutzerdefinierten Getter, der Daten langsam lädt. Etwas wie dieses Snippet ist gut für das Nicht-Multithreading-eviroment:

%Vor%

Auf diese Weise werden Daten immer neu geladen, wenn Sie sie in Speicherwarnungen

"freigeben"     
Andrea 11.10.2013 15:08
quelle
0

Die Methode ViewDidLoad wird nur einmal aufgerufen, wenn ViewController initialisiert wird. Wenn Sie einige Daten erneut in Ihr NSArray laden müssen, sollten Sie bei Bedarf Ihre eigenen Methoden aufrufen.

Wenn dieses Array von verschiedenen Teilen des Codes verwendet wird, sollten Sie vielleicht darüber nachdenken, Ihre Codestruktur neu zu gestalten, um eine große Konzentration von Daten in nur einem Objekt zu vermeiden.

Edit: Wie von @occulus in den Kommentaren gezeigt, wird es nicht aufgerufen, wenn die View initialisiert wird, sondern wenn die View vom ViewController geladen wird .. mein Fehler

    
Jão 31.05.2013 10:12
quelle
0

Als Beispiel hatte ich eine App, die Daten in eine sehr lange Tabellenansicht (potenziell 1000 Datensätze) heruntergeladen hat. Um dies zu unterstützen, habe ich ein "Sparse" -Array implementiert, das leere Elemente erlaubt, die über das Netz "hereingestolpert" werden, wenn sie referenziert werden (mit einem "Download" -Indikator in der Tabellenzelle während des Herunterladens).

Dies wurde manipuliert, so dass, wenn didReceiveMemoryWarning auftrat, das Array gelöscht wurde, wobei ein zuletzt benutzter Algorithmus verwendet wurde, um die ältesten N% des Arrays zu löschen. Die Wiederherstellung würde automatisch erfolgen - die geleerten Zellen würden neu geladen, wenn sie referenziert wurden.

Nicht, dass ich dieses spezifische Schema empfehle, aber beachte die generellen Eigenschaften von vielen Daten, eine Möglichkeit zu "priorisieren", was gelöscht werden sollte, und eine "sanfte" Möglichkeit, die Daten neu zu laden (im Idealfall nur Nachladen) die Teile, die in naher Zukunft benötigt werden).

    
Hot Licks 31.05.2013 19:40
quelle