Comment viewController peut-il se releaser?

yodarkyodark Membre
03:37 modifié dans API UIKit #1
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 ?


- (IBAction)exit {<br />&nbsp; &nbsp; <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 ?

Réponses

  • BaardeBaarde Membre
    03:37 modifié #2
    Tout dépend de la manière dont ton viewController a été créé.

    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 :
    [self release];
    


    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 :
    self.view = nil;
    
  • 03:37 modifié #3
    En effet tu n'appelles jamais [self release]; dans tes sous-classe.
    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!
    - (void)dealloc
    

    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 :
    - (void)dealloc<br />{<br />[myArray release];<br />[super dealloc];<br />}<br />
    


    de la meme manière, Toto.h aura comme ivar ton viewController :
    <br />MyViewController* myViewController;<br />
    


    Toto.m instancie myViewController :
    <br />- (IBAction)create(id)sender<br />{<br />&nbsp;  [self destruction:nil];<br /><br />&nbsp;  myViewController = [[MyViewController alloc] initWithNibName:@&quot;Test&quot; bundle:[NSBundle mainBundle]];<br />}<br /><br />- (IBAction)destruction:(id)sender<br />{<br />&nbsp; &nbsp;  if(myViewController!=nil){<br />&nbsp; &nbsp; &nbsp; &nbsp; [myViewController release];<br />&nbsp; &nbsp; &nbsp; &nbsp; myViewController=nil;<br />&nbsp; &nbsp; }<br />}<br />
    
  • GreensourceGreensource Membre
    03:37 modifié #4
    Je m'incruste ;)
    Est)ce important l'ordre de [super dealloc];
    dans la méthode dealloc? Moi je le met toujours en premier ça change quelque chose?
  • yodarkyodark Membre
    03:37 modifié #5
    Donc si je comprends bien il faut absolument que mon controlleur de vue soit une variable d'instance (c'est ce que veut dire ivar?) afin que je puisse le récupérer n'importe ou dans le code et puis le fermer
    Jusqu'à  présent j'avais toujours fait :

    ResultViewController * mResultViewController =&nbsp; [[ResultViewController alloc] initWithNibName:@&quot;resultView&quot; bundle:nil];<br />[mResultViewController getGameController:self];
    


    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]


  • AliGatorAliGator Membre, Modérateur
    juin 2009 modifié #6
    2 précisions :

    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
  • zoczoc Membre
    juin 2009 modifié #7
    dans 1245827982:

    Est)ce important l'ordre de [super dealloc];
    dans la méthode dealloc? Moi je le met toujours en premier ça change quelque chose?


    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...
Connectez-vous ou Inscrivez-vous pour répondre.