Je surfe sur le merveilleux blog maintenu par Scott Stevenson, et j'essaie de comprendre un concept fondamental d'Objectif-C consistant à attribuer aux délégués la propriété «assigner» vs «retenir». Notez que les deux sont identiques dans un environnement garbage collection. Je suis principalement concerné par un environnement non basé sur GC (par exemple: iPhone).
Directement du blog de Scott:
"Le mot-clé assign générera un setter qui attribue directement la valeur à la variable d'instance, plutôt que de la copier ou de la conserver. C'est mieux pour les types primitifs comme NSInteger et CGFloat, ou les objets que vous ne possédez pas directement, tels que les délégués."
Qu'est-ce que cela signifie que vous ne possédez pas directement l'objet délégué? Je retiens généralement mes délégués, parce que si je ne veux pas qu'ils partent dans l'abîme, retenez s'en chargera pour moi. J'abstrait généralement UITableViewController de sa source de données respective et de son délégué également. Je conserve également cet objet particulier. Je veux m'assurer qu'il ne disparaît jamais afin que mon UITableView ait toujours son délégué.
Quelqu'un peut-il expliquer davantage où / pourquoi je me trompe, afin que je puisse comprendre ce paradigme courant dans la programmation Objective-C 2.0 d'utiliser la propriété assign sur les délégués au lieu de retenir?
Merci!
la source
Réponses:
La raison pour laquelle vous évitez de conserver les délégués est que vous devez éviter un cycle de conservation:
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 possède A, ainsi le dealloc de A ne serait jamais appelé, provoquant une fuite à la fois de A et de B.
Vous ne devriez pas vous inquiéter de la disparition de A car il possède B et s'en débarrasse ainsi dans dealloc.
la source
weak
? La question est de savoir pourquoi utiliserassign
au lieu deweak
?assign
place deretain
. La question est plus ancienne que l'ARC;weak
etstrong
(ce dernier étant synonyme deretain
) n'existait pas avant l'introduction de l'ARC. Vous devriez poser votre question surweak
vsassign
séparément.Parce que l'objet qui envoie les messages de 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. Ceci, bien sûr, est 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 des pairs: ni l'un ni l'autre ne possède l'autre, probablement parce qu'ils appartiennent tous deux au même troisième objet.
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, au fait. Je ne me souviens pas de quoi il s'agissait, et je ne pense pas qu'il y ait une bonne raison à cela.)
Addendum (ajouté le 19/05/2012): Sous ARC, vous devez utiliser à la
weak
place deassign
. Les références faibles sontnil
automatiquement définies lorsque l'objet meurt, ce qui élimine la possibilité que l'objet déléguant finisse par envoyer des messages au délégué mort.Si vous vous éloignez d'ARC pour une raison quelconque, modifiez au moins les
assign
propriétés qui pointent vers des objetsunsafe_unretained
, ce qui indique clairement qu'il s'agit d'une référence non conservée mais non nulle à un objet.assign
reste approprié pour les valeurs non-objet sous ARC et MRC.la source
NSURLConnection
conserve son délégué.weak
, mais cela ne répond pas à la question initiale: pourquoi Apple utilise-t-il à laassign
place deweak
?assign
plutôt que conservées »;weak
n'existait pas quand on l'a demandé. Votre question est différente, que vous devriez poser séparément. Je serais ravi d'y répondre.Notez que lorsque vous avez un délégué qui est assigné, il est très important de toujours définir cette valeur de délégué sur nil chaque fois que l'objet va être désalloué - donc un objet doit toujours faire attention à nil out les références de délégué dans dealloc si ce n'est pas le cas. fait ailleurs.
la source
L'une des raisons derrière cela est d'éviter les cycles de rétention. Juste pour éviter le scénario où A et B se référencent tous les deux des objets et aucun d'eux n'est libéré de la mémoire.
L' affectation effective est préférable pour les types primitifs tels que NSInteger et CGFloat, ou les objets que vous ne possédez pas directement, tels que les délégués.
la source