2010-03-12 8 views
45

Ich habe eine einfache Location-aware iPhone-Anwendung entwickelt, die funktionell sehr gut zu unseren Erwartungen funktioniert, außer in dem niedrigen Speicherzustand des Telefons.Wie didReceiveMemoryWarning implementieren?

Im Low-Memory-Zustand des Telefons stürzt meine App einfach ab und wenn ich den Speicher des Telefons durch die Freigabe von etwas Speicherplatz erhöht wieder gut funktionieren ohne Absturz.

Als ich etwas über das Problem gegoogelt habe, habe ich festgestellt, dass das Betriebssystem didReceiveMemoryWarning in den Low-Memory-Bedingungen an alle Controller in der aktuellen Hierarchie sendet, so dass jeder von ihnen die Methode didReceiveMemoryWarning implementieren und Iboutlet auf Null setzen sollte die Ansicht, die derzeit nicht sichtbar ist.

Ich habe auch irgendwo gelesen, dass, wenn die Ansicht für diesen Controller nicht sichtbar ist die Methode setView mit Null-Parameter aufgerufen wird und wenn einige Outlet-Variablen angefügt sind, wird es Probleme beim Entfernen von ihnen sein.

Also mit all diesem fundas, was das Beste ist niedriges Niveau Speicherzustand durch die Iphone angehoben zu handhaben durch die Umsetzung des didReceiveMemoryWarning und ViewDidUnload Methoden.

Bitte geben Sie ein geeignetes Beispiel oder Link, wenn möglich für die Lösung des obigen Problems.

danke.

+0

http://stackoverflow.com/questions/491075/iphone-development-simulation-memory-warning – harshalb

+0

Beispielhafte Frage! – bobobobo

Antwort

20

Ein Beispiel ich bin veröffentlichen ..., die ich von somwhere kopiert haben ... es könnte Ihnen eine Idee geben ...

- (void)didReceiveMemoryWarning { 

    // Release anything that's not essential, such as cached data (meaning 
    // instance variables, and what else...?) 

    // Obviously can't access local variables such as defined in method 
    // loadView, so can't release them here We can set some instance variables 
    // as nil, rather than call the release method on them, if we have defined 
    // setters that retain nil and release their old values (such as through use 
    // of @synthesize). This can be a better approach than using the release 
    // method, because this prevents a variable from pointing to random remnant 
    // data. Note in contrast, that setting a variable directly (using "=" and 
    // not using the setter), would result in a memory leak. 
    self.myStringB = nil; 
    self.myStringD = nil; 
    [myStringA release];// No setter defined - must release it this way 
    [myStringC release];// No setter defined - must release it this way 

    /* 3. MUST CONFIRM: NOT necessary to release outlets here - See override of 
     setView instead. 
    self.labelA = nil; 
    self.imageViewA = nil; 
    self.subViewA = nil; 
    */ 
    // Releases the view if it doesn't have a superview 
    [super didReceiveMemoryWarning]; 
} 
+0

Hey mihir Ich habe iBoutlets und ich lade meine Ansicht aus der Nib-Datei, überprüfen Sie einfach den Kommentar zu meiner Frage. Es ist verwirrend, da die Ansicht nicht sichtbar ist und dann die viewDidUnaload aufgerufen wird. Was soll ich tun, um die Werte in didReceiveMemoryWarning oder viewDidUNload oder setView ???????? – harshalb

+0

aber für jede Ansicht wird die didReceiveMemoryWarning-Funktion getrennt, also implementieren Sie diese Methode in Bezug auf diese bestimmte Ansicht ... in der ViewDidUnload-Methode verwenden Sie die entsprechende Accessor-Methode, um den Wert des Objekts auf Null ... –

+0

Hi sind Sie sicher, dass [ super didReceiveMemoryWarning]; müssen nach dem Freigeben von Objekten –

5

Es liegt an Ihnen zu entscheiden, was in didReceiveMemoryWarning zu tun ist. Das Betriebssystem sagt dir, dass die Speicherkapazität niedrig ist und du so viel wie möglich frei machen musst, sobald du kannst. Die Idee ist, dass Sie zwischengespeicherte Daten freigeben, Ansichten, die nicht sichtbar sind, entladen usw. Die Details sind anwendungsspezifisch.

3

Sie auch Speicher in didReceiveMemoryWarning lösen könnte, dass Sie für die statische zugewiesen Variablen in Ihren Klassen. Denn sobald der Speicher für statische Variablen zugewiesen ist, wird er während der Anwendungsläufe nicht mehr freigegeben.

+1

Es gibt einen kleinen Abschnitt „Memory Warnungen“ auf dieser Seite: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html – schaechtele

+0

dieser jetzt habe ich keinen tag mehr einen anderen link gefunden anstatt – codercat

2

Zu meiner Überraschung implementieren nur ein paar Apps in den offiziellen iPhone-Beispielen didReciveMemoryWarning. Sie können das iPhoneCoreDataRecipes-Beispiel als Referenz verwenden.

Einige Proben (z TableViewSuite) tun auch etwas anderes ;-)

14

Speicher Warnungen ein Signal an Sie sind, dass Sie über alle Ressourcen verfügen sollte, die nicht unbedingt entscheidend sind. Die meisten Ihrer Controller hängen an Datencaches, Zwischendaten oder anderen Kleinigkeiten, um die Neuberechnung zu speichern. Wenn sie Speicherwarnungen erhalten, sollten sie anfangen zu spülen, was sie nicht sofort benötigen, um zu funktionieren.

Wie Sie feststellen, was "kritisch" ist, hängt vollständig vom Design Ihrer Anwendung ab. Ein OpenGL-Spiel zum Beispiel kann bestimmen, dass Texturen, die gegenwärtig auf dem Bildschirm sind, wertvoll sind und Texturen, die nicht sichtbar sind, oder Pegeldaten, die außerhalb der Grenzen des aktuellen Spielbereichs sind, ausblenden. Eine Anwendung mit umfangreichen Sitzungsprotokollen (wie ein IRC-Client) kann sie aus dem Speicher und auf die Festplatte spülen.

Wie Sie festgestellt haben, wird die Warnung an jeden Controller in Ihrer Hierarchie gesendet, so dass jedes Stück einzeln festlegen muss, welche Daten "kritisch für den Betrieb" und was "entbehrlich" sind. Wenn Sie sie alle optimiert haben und immer noch Warnungen aus dem Speicher erhalten, ist es leider Zeit, das Design Ihrer Kernanwendung zu überdenken, da Sie die Grenzen der Hardware überschreiten.

+0

OK ich habe meine lösung gemacht indem ich die outlets nil in meiner ViewDidUnload methode mache. – harshalb

15

Auf iOS 5 und früher.

Wenn der Controller eine Speicherwarnung erhält, wird didReceiveMemoryWarning aufgerufen. Wenn zu diesem Zeitpunkt die Ansicht des Controllers nicht in der Ansichtshierarchie angezeigt wird, wird die Ansicht auf null gesetzt und viewDidUnload wird automatisch aufgerufen. Also müssen wir in viewDidUnload die in viewDidLoad erstellte oder in Nib erstellte Unteransicht freigeben. Wie folgt:

- (void)viewDidUnload 
{ 
    self.subView = nil; 
    self.subViewFromNib = nil; 
} 

- (void)didReceiveMemoryWarning 
{ 
    self.someDataCanBeRecreatedEasily = nil; 
    [super didReceiveMemoryWarning]; 
} 

Auf iOS6.

Die Steuerung gibt die Ansicht nicht automatisch frei, wenn eine Speicherwarnung empfangen wird. So wird der viewDidUnload nie aufgerufen. Aber wir müssen unsere Ansicht (einschließlich Unteransicht) immer noch freigeben, wenn eine Memry-Warnung auftritt. So.

- (void)didReceiveMemoryWarning 
{ 
    if ([self isViewLoaded] && [self.view window] == nil) { 
     self.view = nil; 
     self.subView = nil; 
     self.subViewFromNib = nil; 
    } 
    self.someDataCanBeRecreatedEasily = nil; 
    [super didReceiveMemoryWarning]; 
} 

Beachten Sie, dass wir [Self View] nicht aufrufen, bevor wir wissen, dass die Ansicht geladen ist. Ursache Die Methode lädt die Ansicht automatisch, wenn die Ansicht nicht geladen ist.

Beachten Sie, dass wir die Ansicht nur freigeben können, wenn die Ansicht nicht zu einem Fenster hinzugefügt wird.

+1

Eigentlich sollten Sie nach 'if (! [Self isViewLoaded] || [self.view window] == nil)' suchen. Sie möchten in beiden Fällen Ihre Subviews und andere Dinge aufräumen. –

Verwandte Themen