web-dev-qa-db-fra.com

ARC - La signification de __unsafe_unretained?

Je veux juste m'assurer d'avoir bien compris:

  1. Est ce que j'ai besoin de __unsafe_unretain objets que je ne possède pas?
  2. Si un objet est __unsafe_unretained Dois-je utiliser assign dans le @property? Cela signifie-t-il que l'objet n'est pas conservé et se réfère simplement à l'objet auquel j'assigne?
  3. Quand voudrais-je l'utiliser sauf pour les délégués?
  4. Est-ce un truc ARC ou était-il utilisé auparavant?
76
shannoga

Le compilateur LLVM 3.0 introduit quatre nouveaux qualificatifs de propriété: __strong, __autoreleasing, __unsafe_unretained, et __weak. Les trois premiers sont disponibles même en dehors d'ARC, selon la spécification .

Comme Joshua l'indique, par défaut, tous les pointeurs sont supposés être __strong sous ARC. Cela signifie que lorsqu'un objet est affecté à ce pointeur, il est conservé aussi longtemps que ce pointeur s'y réfère. C'est bien pour la plupart des choses, mais cela ouvre la possibilité de conserver les cycles, comme je le décris dans ma réponse ici . Par exemple, si vous avez un objet qui contient un autre objet en tant que variable d'instance, mais que le deuxième objet a un lien fort vers le premier en tant que délégué, les deux objets ne seront jamais libérés.

C'est pour cette raison que le __unsafe_unretained et __weak des qualificatifs existent. Leur utilisation la plus courante est pour les délégués, où vous définiriez une propriété pour ce délégué avec weak ou unsafe_unretained attribut (assign est effectivement unsafe_unretained), puis faites correspondre cela en marquant la variable d'instance respective avec __weak ou __unsafe_unretained. Cela signifie que la variable d'instance déléguée pointera toujours vers le premier objet, mais cela n'entraînera pas la conservation de cet objet, interrompant ainsi le cycle de rétention et autorisant la libération des deux objets.

Au-delà des délégués, cela est utile pour rompre tout autre cycle de rétention qui pourrait se former dans votre code. Utilement, l'instrument Leaks comprend maintenant une vue Cycles, qui montre les cycles de rétention qu'il découvre dans votre application de manière graphique.

Tous les deux __unsafe_unretained et __weak empêcher la rétention d'objets, mais de manière légèrement différente. Pour __weak, le pointeur sur un objet sera converti en nil sur la désallocation de l'objet vers lequel il pointe, ce qui est un comportement très sûr. Comme son nom l'indique, __unsafe_unretained continuera de pointer vers la mémoire où se trouvait un objet, même après sa désallocation. Cela peut entraîner des plantages en raison de l'accès à cet objet désalloué.

Pourquoi voudriez-vous utiliser __unsafe_unretained puis? Malheureusement, __weak n'est pris en charge que pour iOS 5.0 et Lion en tant que cibles de déploiement. Si vous souhaitez revenir à iOS 4.0 et Snow Leopard, vous devez utiliser le __unsafe_unretained qualificatif, ou utilisez quelque chose comme Mike Ash MAZeroingWeakRef .

188
Brad Larson
  1. Non, vous pouvez également utiliser weak pour les objets qui ne vous appartiennent pas.
  2. Non, vous pouvez également utiliser unsafe_unretained sur la propriété.
  3. Ma compréhension est que unsafe_unretained les éléments sont comme weak, sans la sécurité supplémentaire de les effacer lorsque l'élément vers lequel ils pointent est libéré (et les frais généraux qui vont avec).
  4. C'est entièrement une chose ARC.
4
dasblinkenlight

__unsafe_unretained est identique à ce qu'était le stockage par défaut d'un objet avant ARC. Avec ARC, la valeur par défaut est désormais __strong ce qui signifie que vous y avez une référence jusqu'à ce que votre référence soit hors de portée.

4
Joshua Weinberg

Une autre observation sur __unsafe_unretained: J'ai des plantages dans mon application sur l'appareil et PAS sur le simulateur avec iVars déclaré __unsafe_unretained! Oui, c'était un bogue dans le code de la migration ARC, mais c'était la première fois que je remarquais une telle différence entre l'appareil et le simulateur.

1
Gerd