Dans Cocoa, dois-je supprimer un objet de la réception des notifications KVO lors de sa désallocation ?

StackOverflow https://stackoverflow.com/questions/13927

  •  08-06-2019
  •  | 
  •  

Question

Quand j'ai enregistré un objet foo pour recevoir des notifications KVO d'un autre objet bar (en utilisant addObserver :...), si je désalloue ensuite foo dois-je envoyer un removeObserver:forKeyPath: Message à bar dans -dealloc ?

Était-ce utile?

La solution

Vous devez utiliser -removeObserver:forKeyPath: retirer l'observateur avant -[NSObject dealloc] fonctionne, alors oui, je le fais dans le -dealloc la méthode de votre classe fonctionnerait.

Mieux que cela, ce serait d'avoir un point déterministe où le propriétaire de l'objet qui effectue l'observation pourrait lui dire que c'est fait et qu'il sera (éventuellement) désalloué.De cette façon, vous pouvez arrêter d'observer immédiatement lorsque l'objet qui effectue l'observation n'est plus nécessaire, quel que soit le moment où il est réellement libéré.

Il est important de garder cela à l’esprit car la durée de vie des objets dans Cocoa n’est pas aussi déterministe que certaines personnes semblent le penser.Les différents frameworks Mac OS X eux-mêmes volonté envoyez vos objets -retain et -autorelease, prolongeant leur durée de vie au-delà de ce que vous pourriez autrement penser.

De plus, lorsque vous effectuez la transition vers le garbage collection Objective-C, vous constaterez que -finalize se déroulera à des moments et dans des contextes très différents de ceux -dealloc a fait.D'une part, la finalisation a lieu sur un fil de discussion différent, donc vous ne peut pas envoyer en toute sécurité -removeObserver:forKeyPath: à un autre objet dans un -finalize méthode.

Tenez-vous-en à la gestion de la mémoire (et des autres ressources rares) dans -dealloc et -finalize, et utilisez un autre -invalidate méthode pour qu'un propriétaire indique à un objet que vous en avez fini avec lui à un point déterministe ;faire des choses comme supprimer les observations KVO là-bas.L'intention de votre code sera plus claire et vous aurez moins de bugs subtils à corriger.

Autres conseils

Un peu d'informations supplémentaires que j'ai acquises grâce à une expérience douloureuse :bien que NSNotificationCenter utilise la remise à zéro des références faibles lors de l'exécution sous garbage collection, ce n'est pas le cas de KVO.Ainsi, vous pouvez vous en sortir sans supprimer un observateur NSNotificationCenter lorsque vous utilisez GC (lors de l'utilisation de rétention/libération, vous devez toujours supprimer votre observateur), mais vous devez toujours supprimer vos observateurs KVO, comme le décrit Chris.

Tout à fait d'accord avec Chris sur le commentaire "S'en tenir à la gestion de la mémoire (et d'autres ressources rares) dans -dealloc et -finalize...".Souvent, je vois des gens essayer d'invalider les objets NSTimer dans leurs fonctions de désallocation.Le problème est que NSTimer conserve ses cibles.Ainsi, si la cible de ce NSTimer est soi-même, dealloc ne sera jamais appelé, ce qui entraînerait des fuites de mémoire potentiellement désagréables.

Invalider dans -invalidate et effectuez un autre nettoyage de la mémoire dans votre dealloc et finalize.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top