Comment viewController peut-il se releaser?
Bonjour à tous,
Ma question est assez simple...
J'ai un controleur de vue qui joue par exemple des sons et fait de l'animation. Quand l'utilisateur touche fermer. J'enlève la vue et surtout mon controlleur de vue n'a plus raison d'être. Je voudrais le releaser. Comment faire ?
Voici mon code. Le problème est que le viewControlleur continue de d'exister et donc d'agir... Pourquoi ?
Ma question est assez simple...
J'ai un controleur de vue qui joue par exemple des sons et fait de l'animation. Quand l'utilisateur touche fermer. J'enlève la vue et surtout mon controlleur de vue n'a plus raison d'être. Je voudrais le releaser. Comment faire ?
- (IBAction)exit {<br /> <br /> [self.view removeFromSuperview];<br /> [self release];<br /> <br />}
Voici mon code. Le problème est que le viewControlleur continue de d'exister et donc d'agir... Pourquoi ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
S'il a été chargé depuis le fichier MainWindow.nib (c'est le cas de tous les viewController dans les templates du SDK), il ne FAUT PAS tenter de le libérer. De nombreux autres objets chargés depuis le nib ont des interactions avec lui. Le détruire serait une mauvaise idée.
Dans les autres cas, le viewController a été créé quelque part dans le code et est certainement retenu en tant que variable d'instance par un autre viewController ou bien le délégué de l'application. Il suffit alors de le remplacer par un autre viewController pour qu'il soit libéré automatiquement (sauf si encore autre chose l'utilise).
De manière générale, à moins qu'un objet se retienne lui-même (ce qui me semble être une mauvaise idée) ou qu'il souhaite se détruire en cours d'initialisation (suite à erreur, dans ce cas init doit renvoyer nil), on ne doit pas écrire le code suivant :
Un viewController occupe peu de mémoire. Il n'est donc pas nécessaire de chercher à le détruire à tout prix. Par contre, tu peux gagner beaucoup en supprimant sa vue :
Il faut que ça soit la classe "maà®tresse", celle qui va gérer l'initialisation de "MyViewController" qui gère ça.
Autrement dis, si Toto.m instancie "MyViewController" avec -initWithNibName:bundle:, c'est Toto.m qui devra faire [myViewController release];
Attention aussi à bien gérer la mémoire dans MyViewController, le dealloc est là pour ça!
est appelé lorsque l'objet reçoit un release. Donc si myViewController reçoit un release, il va automatiquement appeler son dealloc.
Normalement sa vue est automatiquement released, donc les seules choses que tu dois relâcher c'est surtout tes ivars initialisée avec -init (ex : MyViewController.h -> NSArray* myArray; \\ MyViewController.m -> myArray = [[NSArray alloc] init];)
là il faudra implémenter :
de la meme manière, Toto.h aura comme ivar ton viewController :
Toto.m instancie myViewController :
Est)ce important l'ordre de [super dealloc];
dans la méthode dealloc? Moi je le met toujours en premier ça change quelque chose?
Jusqu'à présent j'avais toujours fait :
Sinon pour appeler une méthode qui ferme mon contrôleur fille depuis le contrôleur de vue parent. Il faut que je passe en paramètre le contrôleur parent au controlleur fille ? Ainsi quand l'utilisateur clique sur fermer
[Controlleurparent closeControlleurfille]
1) Le dealloc n'est jamais à appeler nous-même, il est appelé automatiquement... mais pas '"à chaque fois que l'objet reçoit un release", mais seulement quand l'objet est désalloué, c'est à dire quand son retainCount passe à zéro. C'est à dire quand l'objet a reçu autant de "release" qu'il avait reçu de {"retain"+"init..."+"copy..."} avant.
Relire les docs Apple sur la gestion de la mémoire et le reference counting pour plus de précisions, tout est expliqué et détaillé dedans de façon propre.
2) Je pense que l'ordre dans le dealloc est important, en tout cas ça me parait évidemment plus logique de mettre le [tt][super dealloc][/tt] à la FIN de la méthode dealloc : c'est quand même plus logique de demander au parent de se supprimer une fois qu'on a déjà fait le ménage chez nous. Si tu dois éliminer une bouteille d'eau, tu commences par vider l'eau avant de jeter la bouteille... et pas l'inverse !
Et surtout mettre le [tt][super dealloc[/tt] avant la fin de la méthode [tt]-dealloc[/tt] est à mon avis limite risqué (et donc à éviter), puisque tu peux très bien le temps que la méthode dealloc se termine avoir besoin des méthodes et variables de la classe parente (qui auront été supprimées de la mémoire su ti as fait le super [tt][dealloc avant][/tt]).
Si tu détruis la bouteille avant de vider l'eau, tu risques d'avoir une inondation... et aussi plus de mal à te débarasser de l'eau que si tu l'avais vidée dans l'évier avant de détruire la bouteille :P Et ça peut vite faire des dégâts :P
Quand vous jetez une canette de bière à la poubelle, vous la videz avant ou après ?Â
Evidemment que la position du [super dealloc] est importante. Elle doit toujours se situer à la fin, afin de désallouer le contenu avant de désallouer le contenant...
Edit: Ah zut, j'avais pas lu en entier la réponse d'AliGator...
Il faut bien comprendre qu'au final, le dealloc de NSObject va libérer la mémoire utilisée par l'objet. Donc au retour du dealloc, l'espace mémoire qui était utilisé par les variables membres de l'instance est disponible pour une autre allocation.
En mettant le [super dealloc] au début de la méthode dealloc, on prend le risque que les messages suivants envoyés aux membres (en principe des release) soient envoyés vers des objets qui n'existent plus en mémoire officiellement, voir pire, d'autres objets qui auraient pris leur place (par exemple si entre temps un autre thread a fait une allocation...). C'est comme cela qu'on obtient des applications qui plantent aléatoirement...