1

Je l'ai fait un peu de lecture et je l'ai trouvé beaucoup de choses sur comment choses, mais pas pourquoi:Pourquoi utiliserais-je jamais une référence faible?

D'après ce que j'ai lu, le comptage de référence automatique rend la gestion de la mémoire beaucoup plus facile que ça aurait été dans le passé. Si je comprends bien, il est analogue à la collecte des ordures en Java, la différence étant qu'il est pris en charge au moment de la compilation et non pas à l'exécution. C'est à dire. le compilateur insère du code qui conserve la trace du nombre de références d'un objet, puis le désaffecte lorsque ce compte atteint 0.

Dans le code que j'ai écrit jusqu'à présent, j'ai eu pas mal de problèmes avec les objets disparaissant à cause de ARC les désaffectant parce que je n'avais pas utilisé de référence forte. Ma prise de ces problèmes est toujours toujours toujours une référence forte!

Donc, ma question est pourquoi existe-t-il des références faibles? C'est à dire. Quand devrais-je, en tant que développeur, vouloir une référence à un objet sur lequel je ne peux pas compter pour ne pas être désaffecté à mon insu?

+2

Java a de faibles références, vous savez. :) –

+2

FYI - ARC n'est pas analogue à la collecte des ordures. ARC est simplement le compilateur qui ajoute automatiquement les appels à 'retain' et' release' pour vous. C'est complètement différent de la collecte des ordures. – rmaddy

+0

L'exemple le plus courant est peut-être le cas où l'objet A a l'objet B comme délégué. L'objet A doit utiliser l'objet B mais il ne le possède pas, et donc il serait faible. – Gruntcakes

Répondre

2

Le comptage des références n'est pas un nettoyage de la mémoire.

Dans un système de comptage de référence tel que Cocoa Touch, le système désaffecte un objet lorsque son compte de référence devient nul.

Maintenant, pensez à écrire une application qui utilise un UITableView. Vous devez fournir un objet pour agir en tant que source de données de la vue de table. Vous utiliserez probablement votre sous-classe UIViewController comme source de données.

Votre contrôleur de vue a probablement une référence à la vue de table. Cela signifie que le nombre de références de la vue table est au moins 1.

Votre vue de table nécessite une référence à sa source de données. Supposons que le contrôleur de vue ne soit plus référencé par rien d'autre que la vue de table et que la vue de table ne soit plus référencée par rien d'autre que le contrôleur de vue. Il est impossible que votre programme utilise à nouveau ces objets, car il n'a aucun chemin de références pouvant mener à l'un ou l'autre objet. Nous pouvons dire que les objets sont "inaccessibles". Même dans ce cas, aucun des objets ne peut être détruit, car chacun a un nombre de références de 1.

Dans Cocoa Touch, ce scénario est appelé cycle de retenue. Un cycle de conservation est mauvais (à moins qu'il ne soit rompu automatiquement lorsqu'un événement se produit, comme un déclenchement de temporisateur ou une fin de contact), car il empêche le système de détruire des objets qui ne seront plus jamais utilisés.

Il s'agit en fait de la différence entre le comptage des références et la récupération de place: un CPG collecte tous les objets auxquels votre programme n'a plus accès. Un système de comptage de référence collecte tous les objets ayant un nombre de références égal à zéro.

Vous pourriez essayer d'écrire votre programme pour remarquer quand le contrôleur de vue et la vue de table ne sont plus nécessaires. Lorsque cela se produit, vous pouvez explicitement rompre le cycle de conservation (par exemple, en définissant la source de données de la vue de table sur zéro). Mais en général, il est difficile de savoir quand aucun des objets n'est accessible. Dans Cocoa Touch, pour empêcher le cycle de rétention dans l'exemple tableau, la vue de table référence sa source de données "faiblement".Il conserve une référence à la source de données, mais n'incrémente ou ne décrémente pas le nombre de références de la source de données. Ainsi, lorsque le contrôleur de vue et la source de données deviennent inaccessibles, le compteur de référence de la vue de table est toujours 1 (car le contrôleur de vue est fortement référencé), mais le compte de référence du contrôleur de vue est 0. Le système libère le contrôleur de vue . Lors de la désallocation, le contrôleur de vue abandonne sa référence à la vue de la table, ce qui fait que le compteur de référence de la vue table est nul, de sorte que le système peut également le libérer.

En vérité, la vue de table n'utilise pas de référence faible ARC (pour autant que je sache). Il utilise ce que ARC appelle une référence __unsafe_unretained, car il a été écrit bien avant ARC. Mais vous devriez utiliser les références faibles d'ARC dans votre code, car elles sont beaucoup plus sûres et plus utiles.

+0

Merci, cette explication était vraiment utile! – Chris

+0

'__unsafe_unretained' est nommé ainsi parce que sous ARC, les références' weak' normales reçoivent automatiquement une valeur de 'nil' une fois que leur objet référencé est désalloué. Puisque vous pouvez envoyer un message «nil» dans Objective-C, cela peut aider à éviter les plantages (généralement). Les références '__unsafe_unretained' ne contribuent pas au nombre de retain, mais si vous en envoyez un après avoir été désalloué, vous obtiendrez une erreur' EXC_BAD_ACCESS' (probablement). –

Questions connexes