51 votes

Comment mettre en œuvre didReceiveMemoryWarning ?

J'ai développé une application iPhone simple qui tient compte de la localisation et qui fonctionne très bien, sauf dans le cas où la mémoire du téléphone est faible.

En cas de faible mémoire 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, elle recommence à fonctionner correctement sans aucun blocage.

Quand j'ai fait quelques recherches sur le problème, j'ai trouvé que dans les conditions de mémoire faible, le système d'exploitation enverra didReceiveMemoryWarning à tous les contrôleurs dans la hiérarchie actuelle, de sorte que chacun d'entre eux devrait implémenter la méthode didReceiveMemoryWarning et également mettre iboutlet à nil pour la vue qui n'est actuellement pas visible.

J'ai également lu quelque part que si la vue de ce contrôleur n'est pas visible, la méthode setView avec un paramètre nul sera appelé et s'il y a des variables de sortie attachées à la vue, il y aura un problème pour les supprimer.

Donc, avec toutes ces données, quelle est la meilleure façon de traiter les problèmes de mémoire de bas niveau soulevés par l'Iphone en mettant en œuvre la méthode de l'utilisateur. didReceiveMemoryWarning y viewDidUnload méthodes.

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

Merci.

21voto

mihir mehta Points 8182

Je vous propose un exemple... que j'ai copié quelque part... il 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.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];
}

15voto

Dan Story Points 4836

Avertissements de mémoire sont un signal que vous devez disposer de toutes les ressources qui ne sont pas absolument essentiel. La plupart de vos contrôleurs de s'accrocher à des caches de données, de données intermédiaires, ou d'autres pièces et de morceaux, souvent pour enregistrer un nouveau calcul. Lorsqu'ils reçoivent des avertissements de mémoire, ils devraient commencer le rinçage tout ce qu'ils n'avez pas immédiatement besoin pour fonctionner.

Comment vous déterminer ce qui est "critique" dépend entièrement de votre conception. Un OpenGL jeu, par exemple, il peut déterminer que les textures actuellement à l'écran sont précieux et rincer les textures qui ne sont pas visibles, ou des données au niveau de ce qui est en dehors des limites de l'actuelle aire de jeu. Une application avec de nombreuses journaux de session (comme un client IRC) peut les effacer de la mémoire et sur le disque.

Comme vous l'avez remarqué, l'avertissement est envoyé à chaque commande de votre hiérarchie, de sorte que chaque pièce doit déterminer individuellement quelles sont les données qui constitue une "critique de l'opération et de ce qui constitue des "consommables". Si vous avez optimisé tous et sont encore en train de mémoire mises en garde, il est malheureusement temps de revoir votre application de base de conception, parce que vous êtes de dépasser les limites du matériel.

15voto

wihing Points 386

Sur iOS 5 et les versions antérieures.

Lorsque le contrôleur reçoit un avertissement de mémoire, didReceiveMemoryWarning sera appelé. À ce moment-là, si la vue du contrôleur n'est pas dans la hiérarchie des vues, la vue sera mise à nil et viewDidUnload sera automatiquement invoqué. Ainsi, ce que nous devons faire dans viewDidUnload est de libérer la sous-vue créée dans viewDidLoad ou créée à partir de Nib. Comme ceci :

- (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. Donc le viewDidUnload ne sera jamais appelé. Mais nous avons toujours besoin de libérer notre vue (y compris la vue secondaire) quand un avertissement de mémoire se produit. Comme ceci.

- (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, car cette méthode chargera automatiquement la vue si elle n'est pas chargée.

Notez que nous pouvons libérer la vue juste quand la vue n'est pas ajoutée à une fenêtre.

5voto

richb Points 1734

C'est à vous de décider ce qu'il faut faire en didReceiveMemoryWarning . Le système d'exploitation vous indique que la mémoire est faible et que vous devez en libérer le plus possible dès que vous le pouvez. 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 à chaque application.

4voto

schaechtele Points 927

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X