124 votes

Est-ce que je dois définir les propriétés à nil dans dealloc lorsque j'utilise ARC?

Je suis en train d'apprendre le comptage automatique de références sous iOS 5. Maintenant, la première partie de cette question devrait être facile:

  1. Est-il correct de dire que je n'ai PAS besoin d'écrire des instructions de libération explicites dans mon dealloc lors de l'utilisation d'ARC? En d'autres termes, est-il vrai que le code suivant ne nécessite pas de dealloc explicite?

    @interface MyClass : NSObject
    @property (strong, nonatomic) NSObject* myProperty;
    @end
    
    @implementation MyClass
    @synthesize myProperty;
    @end
  2. Ma prochaine question, plus importante, provient d'une ligne dans le document Notes de mise à jour sur la transition vers ARC:

    Vous n'avez pas à (en fait, vous ne pouvez pas) libérer les variables d'instance, mais vous pouvez avoir besoin d'appeler [self setDelegate:nil] sur les classes système et autres code qui ne sont pas compilés avec ARC.

    Cela soulève la question : comment savoir quelles classes système ne sont pas compilées avec ARC? Quand devrais-je créer mon propre dealloc et définir explicitement les propriétés à forte rétention sur nil? Dois-je supposer que toutes les classes NS et UI du framework utilisées dans les propriétés nécessitent des deallocs explicites?

Il y a une mine d'informations sur SO et ailleurs sur les pratiques de libération de l'ivar de sauvegarde d'une propriété lors de l'utilisation du suivi manuel des références, mais relativement peu à ce sujet lors de l'utilisation d'ARC.

198voto

Kevin Ballard Points 88866

Réponse courte : non, vous n'avez pas à annuler les propriétés dans dealloc sous ARC.

Réponse longue : Vous ne devez jamais annuler les propriétés dans dealloc, même en gestion manuelle de la mémoire.

En MRR, vous devez libérer vos ivar. Annuler les propriétés signifie appeler les setters, ce qui peut invoquer du code qu'il ne devrait pas toucher dans dealloc (par exemple, si votre classe, ou une sous-classe, remplace le setter). De même, cela peut déclencher des notifications KVO. Libérer l'ivar évite ces comportements indésirables.

Sous ARC, le système libère automatiquement tous les ivars pour vous, donc si c'est tout ce que vous faites, vous n'avez même pas à implémenter dealloc. Cependant, si vous avez des ivars non-objet qui nécessitent un traitement spécial (par exemple, des tampons alloués que vous devez free()), vous devez toujours vous en occuper dans dealloc.

De plus, si vous vous êtes défini en tant que délégué de certains objets, vous devriez rompre cette relation dans dealloc (c'est le fait d'appeler [obj setDelegate:nil]). La remarque sur le fait de le faire sur des classes qui ne sont pas compilées avec ARC fait référence aux propriétés faibles. Si la classe marque explicitement sa propriété délégué comme faible, alors vous n'avez pas à le faire, car la nature des propriétés faibles signifie qu'elles seront annulées pour vous. Cependant, si la propriété est marquée assign, vous devriez l'annuler dans votre dealloc, sinon la classe se retrouve avec un pointeur fantôme et risque probablement de planter si elle essaie de contacter son délégué. Notez que cela s'applique uniquement aux relations non conservées, telles que les délégués.

1voto

Cœur Points 1538

Just to give the opposite answer...

Short answer: non, vous n'avez pas à annuler les propriétés auto-synthétisées dans dealloc sous ARC. Et vous n'avez pas à utiliser le setter pour celles-ci dans init.

Long answer: Vous devriez annuler les propriétés personnalisées synthétisées dans dealloc, même sous ARC. Et vous devriez utiliser le setter pour celles-ci dans init.

Le point est que vos propriétés personnalisées synthétisées devraient être sûres et symétriques en ce qui concerne la nullité.

Un setter possible pour un minuteur :

-(void)setTimer:(NSTimer *)timer
{
    if (timer == _timer)
        return;

    [timer retain];
    [_timer invalidate];
    [_timer release];
    _timer = timer;
    [_timer fire];
}

Un setter possible pour un scrollview, tableview, webview, textfield, ... :

-(void)setScrollView:(UIScrollView *)scrollView
{
    if (scrollView == _scrollView)
        return;

    [scrollView retain];
    [_scrollView setDelegate:nil];
    [_scrollView release];
    _scrollView = scrollView;
    [_scrollView setDelegate:self];
}

Un setter possible pour une propriété KVO :

-(void)setButton:(UIButton *)button
{
    if (button == _button)
        return;

    [button retain];
    [_button removeObserver:self forKeyPath:@"tintColor"];
    [_button release];
    _button = button;
    [_button addObserver:self forKeyPath:@"tintColor" options:(NSKeyValueObservingOptions)0 context:NULL];
}

Alors vous n'avez pas à dupliquer de code pour dealloc, didReceiveMemoryWarning, viewDidUnload, ... et votre propriété peut être en toute sécurité rendue publique. Si vous étiez préoccupé par l'annulation des propriétés dans dealloc, alors il est peut-être temps de revoir vos setters.

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