Comment mettre en œuvre didReceiveMemoryWarning?

J’ai développé une application iPhone simple, sensible à la localisation, qui fonctionne fonctionnellement très bien à nos attentes, sauf dans les conditions de mémoire faible du téléphone.

Dans des conditions de mémoire faible du téléphone, mon application se bloque et si j’augmente la mémoire du téléphone en libérant de l’espace, cela fonctionne à nouveau correctement sans aucun crash.

Quand j’ai fait une recherche sur le problème, j’ai constaté que, dans des conditions de mémoire insuffisante, le système d’exploitation envoyait didReceiveMemoryWarning à tous les contrôleurs de la hiérarchie actuelle, afin que chacun mette en œuvre la méthode didReceiveMemoryWarning. actuellement non visible.

J’ai également lu quelque part que si la vue de ce contrôleur n’est pas visible, la méthode setView avec le paramètre nil sera appelée et si certaines variables de sortie sont associées à la vue, leur suppression sera problématique.

Donc, avec tous ces fonds, quel est le meilleur moyen de gérer les conditions de mémoire de bas niveau soulevées par l’Iphone en implémentant les méthodes didReceiveMemoryWarning et viewDidUnload .

Veuillez donner un exemple ou un lien approprié si possible pour la solution du problème ci-dessus.

Merci.

Un exemple que je publie … que j’ai copié de quelque part … ça pourrait vous donner une idée …

- (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.mySsortingngB = nil; self.mySsortingngD = nil; [mySsortingngA release];// No setter defined - must release it this way [mySsortingngC 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]; } 

Les avertissements de mémoire vous indiquent que vous devez disposer de toutes les ressources qui ne sont pas absolument critiques. La plupart de vos contrôleurs seront stockés dans des caches de données, des données intermédiaires ou d’autres éléments, souvent pour éviter un nouveau calcul. Lorsqu’ils reçoivent des avertissements de mémoire, ils doivent commencer à vider tout ce dont ils n’ont pas immédiatement besoin pour fonctionner.

La façon dont vous déterminez ce qui est “critique” dépend entièrement de la conception de votre application. Un jeu OpenGL, par exemple, peut déterminer que les textures actuellement affichées sont des textures précieuses et non visibles, ou des données de niveau se trouvant hors des limites de la zone de lecture actuelle. Une application avec des journaux de session étendus (comme un client IRC) peut les vider de la mémoire et du disque.

Comme vous l’avez observé, l’avertissement est envoyé à chaque contrôleur de votre hiérarchie, de sorte que chaque élément doit déterminer individuellement quelles données constituent “critiques pour le fonctionnement” et quelles sont les “consommables”. Si vous les avez tous optimisés et que vous ne les utilisez plus, il est malheureusement temps de revoir la conception de votre application principale, car vous dépassez les limites du matériel.

Sur iOS 5 et versions antérieures.

Lorsque le contrôleur reçoit un avertissement de mémoire, didReceiveMemoryWarning sera appelé. A ce moment, si la vue du contrôleur ne se trouve pas dans la hiérarchie des vues, la vue sera définie sur nil et viewDidUnload sera automatiquement appelé. Donc, les choses que nous devons faire dans viewDidUnload est de libérer la sous-vue créée dans viewDidLoad ou créée à partir de Nib. Comme ça:

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

Sur iOS6.

Le contrôleur ne libère pas automatiquement la vue lorsqu’il reçoit un avertissement de mémoire. Ainsi, viewDidUnload ne sera jamais appelé. Mais nous devons encore libérer notre vue (y compris la vue secondaire) lorsqu’un avertissement de mémoire se produit. Comme ça.

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

Notez que nous n’appelons pas [self view] avant de savoir que la vue est chargée. Parce que cette méthode chargera automatiquement la vue si la vue n’est pas chargée.

Notez que nous pouvons libérer la vue juste au moment où la vue n’est pas ajoutée à une fenêtre.

C’est à vous de décider quoi faire dans didReceiveMemoryWarning . Le système d’exploitation vous dit que la mémoire est faible et que vous devez libérer autant de ressources que possible. L’idée est que vous devez libérer toutes les données mises en cache, décharger les vues qui ne sont pas visibles, etc. Les détails sont spécifiques à l’application.

Vous pouvez également libérer de la mémoire dans didReceiveMemoryWarning , que vous avez alloué pour les variables statiques dans vos classes. Car une fois que la mémoire pour les variables statiques est allouée, elle ne sera pas libérée lors de l’exécution de l’application.

À ma grande surprise, seules quelques applications des échantillons officiels d’iPhone implémentent didReciveMemoryWarning . Vous pouvez utiliser l’exemple iPhoneCoreDataRecipes comme référence.

Certains échantillons (par exemple TableViewSuite) font même autre chose 😉