376 votes

Objective-C ARC : strong vs retain et weak vs assign

Il y a deux nouveaux attributs de gestion de la mémoire pour les propriétés introduits par ARC, strong y weak .

En dehors de copy ce qui est évidemment quelque chose de complètement différent, y a-t-il des différences entre strong vs retain y weak vs assign ?

D'après ce que j'ai compris, la seule différence ici est que weak attribuera nil au pointeur, tandis que assign ne le fera pas, ce qui signifie que le programme se plantera lorsque j'enverrai un message au pointeur une fois qu'il aura été libéré. Mais si j'utilise weak cela n'arrivera jamais, car le message envoyé à nil ne fera rien.

Je ne sais pas s'il y a des différences entre strong y retain .

Y a-t-il une raison pour laquelle je devrais utiliser assign y retain dans les nouveaux projets, ou sont-ils en train d'être dépréciés ?

12 votes

Il y a trois nouveaux attributs de gestion de la mémoire pour les propriétés introduits par ARC strong , weak y unsafe_unretained .

5 votes

@NJones Il y a deux attributs de propriété ( weak y strong ) et 4 qualificatifs de durée de vie variable ( __strong , __weak , __unsafe_unretained , __autoreleasing ). Voir les notes de l'ARC ci-dessous.

1 votes

@SnowCrash Il existait une version de Xcode, probablement un aperçu pour développeur, dans laquelle l'utilisation de assign lors de la compilation avec ARC était une erreur. Il y a beaucoup de réponses supprimées à ce sujet. Il semble que cela ait été modifié avant la version finale. unsafe_unretained est l'attribut préféré de bon nombre d'entre nous, les adopteurs précoces. Pour preuve que unsafe_unretained est un attribut valide, consultez le document "Programming With Objective-C" d'Apple, dans la section "Encapsulating Data", sous le titre "Use Unsafe Unretained References for Some Classes". Il est écrit : "Pour une propriété, cela signifie utiliser l'attribut unsafe_unretained :"

615voto

RDC Points 9222

Après avoir lu tant d'articles Stackoverflow et d'applications de démonstration pour vérifier les attributs des propriétés des variables, j'ai décidé de rassembler toutes les informations sur les attributs :

  1. atomique //par défaut
  2. non-atomique
  3. strong=retain //default
  4. faible
  5. retenir
  6. attribuer //par défaut
  7. non sécurisé_non retenu
  8. copie
  9. en lecture seule
  10. lecture/écriture //par défaut

Vous trouverez ci-dessous le lien détaillé de l'article où vous pourrez trouver tous les attributs mentionnés ci-dessus, qui vous aideront certainement. Un grand merci à toutes les personnes qui donnent les meilleures réponses ici !

Attributs de propriétés variables ou Modificateurs dans iOS

1.strong (iOS4 = conserver)

  • ça dit "garde ça dans le tas jusqu'à ce que je ne le pointe plus"
  • en d'autres termes " je suis le propriétaire, vous ne pouvez pas désallouer ceci avant de viser bien avec ce même que retenir ".
  • Vous n'utilisez le terme "fort" que si vous avez besoin de conserver l'objet.
  • Par défaut, toutes les variables d'instance et les variables locales sont des pointeurs forts.
  • Nous utilisons généralement strong pour les UIViewControllers (parents des éléments de l'interface utilisateur).
  • strong est utilisé avec ARC et permet de ne pas avoir à se soucier du nombre de conservations d'un objet. ARC le libère automatiquement pour vous lorsque vous en avez fini avec lui. L'utilisation du mot-clé strong signifie que vous possédez l'objet.

Exemple :

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2,faible -

  • il est dit "gardez ceci tant que quelqu'un d'autre le pointe fortement".
  • c'est la même chose que céder, pas conserver ou libérer
  • Une référence "faible" est une référence que vous ne retenez pas.
  • Nous utilisons généralement le terme "weak" pour les IBOutlets (enfants de UIViewController), car l'objet enfant ne doit exister que tant que l'objet parent existe.
  • une référence faible est une référence qui ne protège pas l'objet référencé contre la collecte par un ramasseur de déchets.
  • La faiblesse est essentiellement une affectation, une propriété non conservée. Sauf que lorsque l'objet est désalloué, le pointeur faible est automatiquement mis à nil.

Exemple :

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

Explication des points forts et des points faibles, Merci à BJ Homer :

Imaginez que notre objet est un chien, et que le chien veut s'enfuir (être désalloué).

Les pointeurs forts sont comme une laisse pour le chien. Tant que vous avez la laisse attachée au chien, celui-ci ne s'enfuira pas. Si cinq personnes attachent leur laisse à un chien, (cinq pointeurs forts à un objet), alors le chien ne s'enfuira pas tant que les cinq laisses ne seront pas détachées.

Les pointeurs faibles, d'un autre côté, sont comme des petits enfants pointant vers le chien en disant "Regardez ! Un chien !" Tant que le chien est toujours sur la laisse, les enfants peuvent toujours voir le chien, et ils vont toujours le pointer vers lui. Mais dès que toutes les laisses sont détachées, le chien s'enfuit. peu importe le nombre d'enfants qui le montrent du doigt.

Dès que le dernier pointeur fort (laisse) ne pointe plus vers un l'objet sera désalloué, et tous les pointeurs faibles seront mis à zéro.

Quand on utilise le mot "faible" ?

La seule fois où vous voudriez utiliser le mot "faible", c'est si vous vouliez éviter les cycles de retenue. (par exemple, le parent retient l'enfant et l'enfant retient le parent, de sorte qu'aucun n'est jamais libéré).

3.retenir = fort

  • il est retenu, l'ancienne valeur est libérée et il est assigné retenir spécifie que la nouvelle valeur doit être envoyée
  • conserver l'affectation et envoyer l'ancienne valeur -libérer
  • retenir, c'est la même chose qu'être fort.
  • apple dit que si vous écrivez retain il sera auto converti/travaillera comme strong only.
  • les méthodes comme "alloc" incluent un "retain" implicite

Exemple :

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.assignation

  • assign est la valeur par défaut et effectue simplement une affectation de variable.
  • assign est un attribut de propriété qui indique au compilateur comment synthétiser l'implémentation du setter de la propriété.
  • J'utiliserais assign pour les propriétés primitives du C et weak pour les références faibles aux objets Objective-C.

Exemple :

@property (nonatomic, assign) NSString *address;

@synthesize address;

7 votes

2. 2. "une référence faible est une référence qui ne protège pas l'objet référencé contre la collecte par un ramasseur d'ordures" - il n'existe pas de ramasseur d'ordures dans l'objectif c ;

0 votes

3. Nous utilisons généralement le terme "weak" pour les IBOutlets (enfants de UIViewController), car l'objet enfant ne doit exister que tant que l'objet parent existe" - Tout est faux. IBOutlet - juste un mot réservé pour dire que cette propriété peut être liée via IB. Les "propriétés IBOutlets" ne sont PAS des enfants !!! Ce sont d'autres objets ! Et comme nous le savons, 'weak' n'empêche pas la désallocation de l'objet, donc UIViewController ne peut pas contrôler combien de temps il existe ! Mais c'est souhaité. Parce que quelqu'un d'autre garde un pointeur fort sur lui. Et sa vue supérieure (la vue supérieure de la propriété IBOutlet). Toutes les vues vivent dans une hiérarchie.

1 votes

Et cette hiérarchie est gérée automatiquement par iOS. Lisez le concept MVC. Je veux dire que lorsque le ViewContorller est présenté, iOS charge sa hiérarchie de vues à l'écran (créant les vues manquantes). Quand un autre ViewController est présenté, cette première hiérarchie de vues est désallouée. Mais si vous avez "strong" dans ViewController, cette vue ne peut pas être désaffectée lorsqu'elle est hors écran. Ce qui pourrait avoir un impact important sur la mémoire de l'appareil et provoquer un ralentissement de l'application. (Bien sûr, les appareils ont beaucoup de mémoire et cela ne pose aucun problème pour les applications à 5 ou 10 écrans, mais pour les grandes applications, vous aurez des problèmes).

235voto

JeremyP Points 46808

De la Transition vers les notes de version ARC (l'exemple dans la section sur les attributs de propriété).

// The following declaration is a synonym for: @property(retain) MyClass *myObject;

@property(strong) MyClass *myObject;

Alors strong est la même chose que retain dans une déclaration de propriété.

Pour les projets ARC, j'utiliserais strong au lieu de retain j'utiliserais assign pour les propriétés primitives de C et weak pour les références faibles à des objets Objective-C.

11 votes

En fait, sous ARC, c'est une erreur de compilation que d'utiliser assign pour un objet. Vous devez utiliser soit weak o unsafe_unretained (ce qui n'est pas sûr, évidemment) si vous ne voulez pas conserver la propriété.

5 votes

assign compile très bien pour moi dans les projets ARC avec la cible de déploiement 4.0.

9 votes

@Pascal : les références faibles ne sont pas autorisées dans les cibles de déploiement où le système d'exploitation n'est pas 5.0 ou plus. Donc, pour les anciens projets, vous pouvez toujours utiliser assign, mais si vous passez à des versions plus récentes, vous devez passer à weak.

43voto

Vadoff Points 1506

non atomique/atomique

  • le non atomique est beaucoup plus rapide que l'atomique
  • utilisez toujours la méthode non atomique à moins que vous n'ayez une exigence très spécifique pour l'atomique, ce qui devrait être rare (l'atomique ne garantit pas la sécurité des threads - il ne fait que bloquer l'accès à la propriété lorsqu'elle est simultanément définie par un autre thread).

fort/faible/assigné

  • utiliser fort pour conserver les objets - bien que le mot clé conserver soit synonyme, il est préférable d'utiliser le mot fort à la place
  • utiliser faible si vous voulez seulement un pointeur sur l'objet sans le conserver - utile pour éviter les cycles de conservation (c'est-à-dire les délégués) - le pointeur est automatiquement annulé lorsque l'objet est libéré.
  • utiliser attribuer pour les primitives - exactement comme weak, sauf qu'il n'y a pas de nil dans l'objet lorsqu'il est libéré (activé par défaut).

(facultatif)

copie

  • l'utiliser pour créer une copie superficielle de l'objet
  • bonne pratique pour toujours mettre les propriétés immuables en copie - parce que les versions mutables peuvent être passées dans les propriétés immuables, la copie garantira que vous aurez toujours affaire à un objet immuable.
  • si un objet immuable est transmis, il le conservera - si un objet mutable est transmis, il le copiera.

en lecture seule

  • l'utiliser pour désactiver la mise en place de la propriété (empêche le code de compiler s'il y a une infraction)
  • vous pouvez changer ce qui est livré par le getter soit en changeant la variable directement via sa variable d'instance, soit dans la méthode getter elle-même.

0 votes

@Sakthimuthiah a raison, vous devez corriger votre réponse.

0 votes

@Sakthimuthiah est incorrect (et toute autre personne qui le dit). Atomic ne rend PAS le thread safe, bien qu'il puisse être facilement confondu en raison de son comportement. Veuillez lire : stackoverflow.com/questions/12347236/

39voto

iMartin Points 4853

Pour autant que je sache, strong y retain sont des synonymes, donc ils font exactement la même chose.

Ensuite, le weak est presque comme assign mais automatiquement mis à nil après que l'objet qu'il pointe soit désalloué.

Cela signifie que vous pouvez simplement les remplacer.

Cependant il y a un cas particulier que j'ai rencontré, où j'ai du utiliser assign plutôt que weak . Disons que nous avons deux propriétés delegateAssign y delegateWeak . Dans les deux est stocké notre délégué, qui nous appartient en ayant la seule référence forte. Le délégué est en train de désallouer, donc notre -dealloc est également appelée.

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething];
    [delegateAssign doSomething];
}

Le délégué est déjà dans le processus de désallocation, mais n'est pas encore complètement désalloué. Le problème est que weak les références à lui sont déjà annulées ! Propriété delegateWeak contient une valeur nulle, mais delegateAssign contient un objet valide (avec toutes les propriétés déjà libérées et annulées, mais toujours valides).

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething]; // Does nothing, already nil.
    [delegateAssign doSomething]; // Successful call.
}

C'est un cas assez spécial, mais il nous révèle comment ces weak les variables fonctionnent et quand elles sont annulées.

0 votes

21voto

Flow Points 698

Le document de Clang sur Objective-C Comptage automatique des références (ARC) explique clairement les qualificatifs et les modificateurs de propriété :

Il y a quatre qualifications de propriété :

  • __ autoreleasing
  • __ fort
  • __*unsafe_unretained*
  • __ faible

Un type est non-trivialement qualifié de propriété s'il est qualifié avec __ autoreleasing , __ fort ou __. faible .

Ensuite, il y a six modificateurs de propriété pour les biens déclarés :

  • attribuer implique une propriété __*unsafe_unretained*.
  • copie implique __ fort ainsi que le comportement habituel de la sémantique de copie sur le setter.
  • retenir implique __ fort propriété.
  • fort implique __ fort propriété.
  • *unsafe_unretained* implique la propriété __*unsafe_unretained*.
  • faible implique __ faible propriété.

À l'exception de faible Ces modificateurs sont disponibles dans les modes non-ARC.

D'un point de vue sémantique, les qualificatifs de propriété ont une signification différente dans le système de gestion de la propriété. cinq opérations gérées : Lecture, Affectation, Initialisation, Destruction et Déplacement, dans lequel la plupart du temps nous ne nous soucions que de la différence dans l'opération d'Affectation.

Affectation se produit lors de l'évaluation d'un opérateur d'affectation. La sémantique de sémantique varie en fonction de la qualification :

  • Pour __. fort le nouveau pointeur est d'abord retenu ; ensuite, la lvalue est chargée avec une sémantique primitive ; enfin, le nouveau pointeur est stocké dans la lvalue avec une sémantique primitive ; et enfin, l'ancien pointeur est libéré. Cette opération n'est pas effectuée de manière atomique ; une synchronisation externe doit être utilisée pour sécuriser cette opération face à des chargements et des stockages concurrents.
  • Pour __. faible la valeur lval est mise à jour pour pointer vers le nouveau pointeur, sauf si le nouveau pointeur est un objet en cours de désallocation, auquel cas la valeur lval est mise à jour vers un pointeur nul. Cette opération doit être exécutée de manière atomique par rapport aux autres affectations à l'objet, aux lectures de l'objet et à la libération finale du nouveau pointeur.
  • Pour les objets __*unsafe_unretained*, la nouvelle pointe est stockée dans la lvalue en utilisant la sémantique primitive.
  • Pour __. autoreleasing le nouveau pointeur est retenu, libéré automatiquement et stocké dans la lvalue en utilisant la sémantique primitive.

L'autre différence dans la Lecture, l'Init, la Destruction et le Déplacement, s'il vous plaît se référer à Section 4.2 Sémantique dans le document .

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