Il existe deux nouveaux attributs de gestion de la mémoire pour les propriétés introduites par ARC: strong
et weak
.
Mis à part copy
, qui est évidemment quelque chose de complètement différent, existe-t-il des différences entre strong
et retain
et weak
et assign
? =
A ma connaissance, la seule différence est que weak
assignera nil
au pointeur, tandis que assign
ne le fera pas, ce qui signifie que le programme se bloquera lorsque j'enverrai un message au pointeur. une fois qu'il est sorti. Mais si j'utilise weak
, cela n'arrivera jamais, car le message envoyé à nil
ne fera rien.
Je ne connais aucune différence entre strong
et retain
.
Y a-t-il une raison pour laquelle je devrais utiliser assign
et retain
dans de nouveaux projets, ou le type de celui-ci est-il déconseillé?
À partir de Notes de publication du passage à ARC (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;
Donc, strong
est identique à 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 C et weak
pour les références faibles à des objets Objective-C.
Après avoir lu tant d'articles et de publications Stackoverflow et d'applications de démonstration pour vérifier les attributs de propriétés variables, j'ai décidé de rassembler toutes les informations sur les attributs:
Ci-dessous, le lien détaillé de l'article où vous pouvez 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é de variable ou modificateurs sous iOS
1.strong (iOS4 = conserver)
Exemple:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.weak -
Exemple :
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Explication forte et faible, Merci à BJ Homer :
Imaginez que notre objet soit un chien et que celui-ci veuille fuir (être désalloué).
Les pointeurs forts sont comme une laisse sur 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 puissants à un objet), le chien ne s'enfuira pas tant que les cinq laisses ne sont pas détachées.
Les pointeurs faibles, par contre, sont comme des petits enfants qui pointent le chien et disent "Regarde! Un chien!" Tant que le chien est toujours en laisse, les petits enfants peuvent toujours le voir et ils le montrent du doigt. Dès que toutes les laisses sont détachées, cependant, le chien s'enfuit, peu importe le nombre de petits enfants qui le désignent.
Dès que le dernier pointeur fort (leash) ne pointe plus vers un objet, celui-ci est désalloué et tous les pointeurs faibles sont mis à zéro.
Quand on utilise faible?
Si vous souhaitez éviter les cycles de rétention (par exemple, le parent conserve l’enfant et l’enfant le conserve, le parent n’est jamais relâché).
3.retain = strong
Exemple:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.assign
Exemple:
@property (nonatomic, assign) NSString *address;
@synthesize address;
Autant que je sache, strong
et retain
sont des synonymes, donc ils font exactement la même chose.
Ensuite, la weak
est presque semblable à assign
, mais elle est automatiquement définie sur nil après que l'objet sur lequel il pointe est désalloué.
Cela signifie que vous pouvez simplement les remplacer.
Cependant, j'ai rencontré un cas spécial dans lequel je devais utiliser assign
plutôt que weak
. Disons que nous avons deux propriétés delegateAssign
et delegateWeak
. Dans les deux cas est stocké notre délégué, c'est-à-dire nous posséder en ayant la seule référence forte. Le délégué désalloue alors notre méthode -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à en cours de désallocation, mais n'est pas encore complètement désalloué. Le problème est que weak
ses références sont déjà annulées! La propriété delegateWeak
contient nil, mais delegateAssign
contient un objet valide (avec toutes les propriétés déjà publiées et annulées, mais toujours valable).
// 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 particulier, mais il nous révèle comment fonctionnent ces variables weak
et quand elles sont annulées.
Le document de Clang sur Comptage de référence automatique Objective-C (ARC) explique clairement les qualificateurs et modificateurs de propriété:
Il existe quatre qualificateurs de propriété:
- __ autoreleasing
- __ fort
- __ * unsafe_unretained *
- __ faible
Un type est qualifié de droit de propriété non indifférent s'il est qualifié avec __ autoreleasing , __ strong ou __ faible.
Il existe ensuite six modificateurs de propriété pour la propriété déclarée:
- assign implique __ * unsafe_unretained * propriété.
- copy implique __ une propriété forte , ainsi que le comportement habituel de la sémantique de la copie sur le setter.
- conserver implique __ propriété forte .
- fort implique __ fort propriété.
- * unsafe_unretained * implique __ * unsafe_unretained * propriété.
- faible implique __ faible propriété.
À l'exception de faible , ces modificateurs sont disponibles en mode non ARC.
Du point de vue de la sémantique, les qualificateurs de propriété ont une signification différente dans les cinq opérations gérées : lecture, affectation, initialisation, destruction et déplacement, dans lesquels la plupart du temps se soucient de la différence dans l'opération d'assignation.
L'affectation se produit lors de l'évaluation d'un opérateur d'affectation. La sémantique varie en fonction de la qualification:
- Pour les objets __ forts , la nouvelle pointee est d'abord conservée; deuxièmement, la lvalue est chargée de sémantique primitive; troisièmement, la nouvelle pointee est stockée dans la lvalue avec une sémantique primitive; et enfin, la vieille pointee est libérée. Ceci n'est pas effectué de manière atomique; la synchronisation externe doit être utilisée pour sécuriser cette opération en cas de chargement et de stockage simultanés.
- Pour les objets __ faibles , la lvalue est mise à jour pour pointer vers la nouvelle pointee, à moins que la nouvelle pointee soit un objet en cours de désallocation, auquel cas la lvalue est mise à jour avec un pointeur nul. . Cela doit s'exécuter de manière atomique par rapport aux autres assignations à l'objet, aux lectures à partir de l'objet et à la libération finale de la nouvelle pointee.
- Pour les objets __ * unsafe_unretained *, la nouvelle pointee est stockée dans la lvalue à l'aide de la sémantique primitive.
- Pour les objets __ autoreleasing , la nouvelle pointee est conservée, autoreleased et stockée dans la valeur lvalue à l'aide de la sémantique primitive.
L'autre différence entre Lecture, Init, Destruction et Déménagement, veuillez vous référer à Section 4.2 Sémantique dans le document .
Pour comprendre les références forte et faible, considérons l'exemple ci-dessous, supposons que nous ayons une méthode nommée displayLocalVariable.
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
Dans la méthode ci-dessus, la portée de la variable myName est limitée à la méthode displayLocalVariable. Une fois la méthode terminée, la variable myName contenant la chaîne "ABC" sera libérée de la mémoire.
Et maintenant, si nous voulons conserver la valeur de la variable myName tout au long du cycle de vie de notre contrôleur de vue. Pour cela, nous pouvons créer la propriété nommée username qui aura une référence forte à la variable myName (voir self.username = myName;
dans le code ci-dessous), comme ci-dessous,
@interface LoginViewController ()
@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Maintenant, dans le code ci-dessus, vous pouvez voir que myName a été assigné à self.username et que self.username a une référence forte (comme nous l'avons déclaré dans l'interface en utilisant @property) à myName (indirectement, il a une référence forte à la chaîne "ABC"). Par conséquent, String myName ne sera pas désalloué de la mémoire tant que self.username n'aura pas été activé.
Maintenant, envisagez d'affecter myName à dummyName, qui est une référence faible, self.dummyName = myName; Contrairement à la référence forte, le nom de la base sera maintenu par myo uniquement jusqu'à ce qu'il y ait une référence forte à myName. Voir ci-dessous le code pour comprendre la référence faible,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
Dans le code ci-dessus, il y a une référence faible à myName (c'est-à-dire que self.dummyName a une référence faible à myName), mais il n'y a pas de référence forte à myName, donc self.dummyName ne pourra pas contenir la valeur myName.
Maintenant, considérez à nouveau le code ci-dessous,
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
Dans le code ci-dessus, self.username a une référence forte à myName. Par conséquent, self.dummyName aura désormais la valeur myName, même après la fin de la méthode, car myName est associé à une référence Strong.
Désormais, chaque fois que nous faisons une référence forte à une variable, son nombre de rétention est augmenté de un et la variable ne sera pas désaffectée. Le nombre de rétention atteint 0.
J'espère que cela t'aides.
Exemple: @property (strong, nonatomic) ViewController * viewController;
@synthesize viewController;
Par défaut, obtenez automatiquement et mettez à zéro
Exemple: @property (faible, non atomique) IBOutlet UIButton * myButton;
@synthèse myButton;
Les différences entre fort et retenir:
Les différences entre faible et assigner: