141 votes

Pourquoi les délégués Objective-C reçoivent-ils généralement la propriété assign au lieu de retain ?

Je navigue sur le merveilleux blog de Scott Stevenson, et j'essaie de comprendre un concept Objective-C fondamental de l'assignation des délégués : la propriété 'assign' par rapport à 'retain'. Notez que les deux sont les mêmes dans un environnement de garbage collected. Je suis surtout préoccupé par un environnement non basé sur le garbage collector (ex : iPhone).

Directement du blog de Scott :

"Le mot-clé assign générera un setter qui affecte la valeur à la variable d'instance directement, plutôt que de la copier ou de la conserver. C'est la meilleure solution pour les types primitifs comme NSInteger et CGFloat, ou les objets que vous ne possédez pas directement, comme les délégués."

Qu'est-ce que cela signifie que vous ne possédez pas directement l'objet délégué ? Je conserve généralement mes délégués, car si je ne veux pas qu'ils disparaissent dans l'abîme, la conservation s'en chargera pour moi. J'abstrais généralement UITableViewController de sa source de données et de son délégué respectifs. Je retiens également cet objet particulier. Je veux m'assurer qu'il ne disparaîtra jamais et que mon UITableView aura toujours son délégué à portée de main.

Quelqu'un peut-il m'expliquer où et pourquoi je me trompe, afin que je puisse comprendre ce paradigme commun à la programmation Objective-C 2.0 qui consiste à utiliser la propriété assign sur les délégués au lieu de retain ?

Merci !

145voto

Andrew Pouliot Points 4684

La raison pour laquelle vous évitez de retenir les délégués est que vous devez éviter une boucle de retenue (plus communément appelée cycle de retenue) :

A crée B A se définit comme le délégué de B A est libéré par son propriétaire

Si B avait conservé A, A ne serait pas libéré, car B est propriétaire de A, et donc le dealloc de A n'aurait jamais été appelé, ce qui aurait causé à la fois A et B de fuir.

Il ne faut pas s'inquiéter de la disparition de A car il possède B et s'en débarrasse donc dans dealloc.

32voto

Peter Hosey Points 66275

Parce que l'objet qui envoie les messages du délégué ne possède pas le délégué.

Souvent, c'est l'inverse, comme lorsqu'un contrôleur se définit comme le délégué d'une vue ou d'une fenêtre : le contrôleur possède la vue/fenêtre, donc si la vue/fenêtre possédait son délégué, les deux objets se posséderaient mutuellement. Il s'agit bien sûr d'un cycle de rétention, similaire à une fuite avec la même conséquence (les objets qui devraient être morts restent vivants).

D'autres fois, les objets sont pairs : aucun ne possède l'autre, probablement parce qu'ils appartiennent tous deux au même objet tiers.

Dans tous les cas, l'objet avec le délégué ne doit pas conserver son délégué.

(Il y a au moins une exception, d'ailleurs. Je ne me souviens pas de ce que c'était, et je ne pense pas qu'il y avait une bonne raison pour cela).


Addendum (ajouté le 2012-05-19) : Sous ARC, vous devez utiliser weak au lieu de assign . Les références faibles sont fixées à nil automatiquement lorsque l'objet meurt, éliminant la possibilité que l'objet délégant finisse par envoyer des messages au délégué mort.

Si vous restez loin de l'ARC pour une raison quelconque, changez au moins assign qui pointent vers des objets à unsafe_unretained qui indiquent explicitement qu'il s'agit d'une référence non conservée mais non nulle à un objet.

assign reste approprié pour les valeurs de non-objets à la fois sous ARC et MRC.

15voto

Notez que lorsque vous avez un délégué qui est assigné, il est très important de toujours mettre la valeur du délégué à nil chaque fois que l'objet va être désalloué - donc un objet devrait toujours faire attention à mettre à nil les références du délégué dans dealloc s'il ne l'a pas fait ailleurs.

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