web-dev-qa-db-fra.com

Dois-je définir des propriétés sur zéro dans dealloc lors de l'utilisation d'ARC?

J'essaie d'apprendre le comptage automatique des références dans iOS 5. Maintenant, la première partie de cette question devrait être facile:

  1. Est-il exact que [~ # ~] pas [~ # ~] besoin d'écrire des instructions explicites de propriété de libération dans mon dealloc lors de l'utilisation d'ARC? En d'autres termes, est-il vrai que les éléments suivants [~ # ~] n'ont pas [~ # ~] besoin d'un 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 du document Transitioning to ARC Release Notes :

    Vous n'êtes pas obligé (en effet, ne pouvez pas) libérer les variables d'instance, mais vous devrez peut-être appeler [self setDelegate: nil] sur les classes système et tout autre code qui n'est pas compilé à l'aide d'ARC.

    Cela soulève la question: comment savoir quelles classes système ne sont pas compilées avec ARC? Quand dois-je créer mon propre dealloc et définir explicitement les propriétés de conservation stricte à zéro? Dois-je supposer que toutes les classes NS et UI Framework utilisées dans les propriétés nécessitent des deallocs explicites?

Il existe une multitude d'informations sur SO et ailleurs sur les pratiques de libération de l'ivar de support d'une propriété lors de l'utilisation du suivi de référence manuel, mais relativement peu à ce sujet lors de l'utilisation d'ARC.

123
emfurry

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

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

Dans MRR, vous devez libérer vos ivars . Remplir les propriétés signifie appeler des setters, qui peuvent 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, il peut déclencher des notifications KVO. La libération de l'ivar évite à la place ces comportements indésirables.

Dans 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 une manipulation spéciale (par exemple des tampons alloués dont vous avez besoin pour free()), vous devez toujours traiter ceux dans dealloc.

De plus, si vous vous êtes défini comme délégué d'un objet, vous devez annuler la définition de cette relation dans dealloc (il s'agit de la partie concernant l'appel de [obj setDelegate:nil]). La remarque à ce sujet sur les classes qui ne sont pas compilées avec ARC est un signe de tête vers les propriétés faibles. Si la classe marque explicitement sa propriété delegate comme weak, vous n'avez pas à le faire, car la nature des propriétés faibles signifie qu'elle sera supprimée pour vous. Cependant, si la propriété est marquée assign, vous devez la supprimer dans votre dealloc, sinon la classe se retrouve avec un pointeur suspendu et se bloquera probablement si elle essaie d'envoyer un message à son délégué. Notez que cela s'applique uniquement aux relations non conservées, telles que les délégués.

197
Lily Ballard

Juste pour donner la réponse inverse ...

Réponse courte: non, vous n'avez pas à annuler les propriétés auto-synthétisées dans dealloc sous ARC. Et vous n'avez pas besoin d'utiliser le setter pour ceux de init.

Réponse longue: Vous devez éliminer les propriétés synthétisées sur mesure dans dealloc, même sous ARC. Et vous devriez utiliser le setter pour ceux de init.

Le fait est que vos propriétés synthétisées sur mesure doivent être sûres et symétriques en ce qui concerne l'annulation.

Un setter possible pour une minuterie:

-(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];
}

Ensuite, vous n'avez pas à dupliquer de code pour dealloc, didReceiveMemoryWarning, viewDidUnload, ... et votre propriété peut être rendue publique en toute sécurité. Si vous étiez inquiet à propos des propriétés nulles dans dealloc, il serait peut-être temps de vérifier à nouveau vos setters.

1
Cœur