Une question 101
Disons que je crée une base de données de voitures et que chaque objet voiture est défini comme suit:
#import <UIKit/UIKit.h>
@interface Car:NSObject{
NSString *name;
}
@property(nonatomic, retain) NSString *name;
Pourquoi est-ce @property(nonatomic, retain) NSString *name;
et non @property(nonatomic, assign) NSString *name;
?
Je comprends que assign
n'incrémentera pas le compteur de référence comme le fera retain
. Mais pourquoi utiliser retain
, puisque name
est membre de l'objet todo
dont la portée est pour lui-même.
Aucune autre fonction externe ne le modifiera non plus.
Il n'y a rien de tel que la "portée d'un objet" dans Objective-C. Les règles de portée n'ont rien à voir avec la durée de vie d'un objet - le nombre de retenues est tout.
Vous devez généralement revendiquer la propriété de vos variables d'instance. Voir les règles de gestion de la mémoire Objective-C . Avec une propriété retain
, votre configurateur revendique la propriété de la nouvelle valeur et renonce à la propriété de l'ancienne. Avec une propriété assign
, le code environnant doit le faire, ce qui est tout aussi gâchis en termes de responsabilités et de séparation des préoccupations. La raison pour laquelle vous utiliseriez une propriété assign
est dans le cas où vous ne pouvez pas conserver la valeur (comme les types non-objet comme BOOL ou NSRect) ou lorsque la conserver entraînerait des effets secondaires indésirables.
Par ailleurs, dans le cas d'une chaîne NSString, le type de propriété correct est généralement copy
. De cette façon, cela ne peut pas changer sous vous si quelqu'un passe dans une NSMutableString (qui est valide - c'est est une sorte de NSString).
et n'oubliez pas d'y accéder via
self.name = something;
car
name = something;
ne se souciera pas des méthodes setter/getter générées mais attribuera plutôt la valeur directement.
Sans retain
, rien ne garantit que NSString*
vous définissez name
avec vivra plus longtemps que l'instruction d'affectation elle-même. En utilisant la propriété retain
pour le setter synthétisé, vous lui permettez d'indiquer au système de gestion de la mémoire qu'il y a au moins un autre objet intéressé à conserver le NSString*
environ.
Le self.
dans:
self.name = something;
est important! Sans cela, vous accédez directement à la variable et contournez le setter.
L'ancien style (corrigez-moi si je me trompe) aurait été:
[self setName:something];
Quoi qu'il en soit, cette notation était le conseil (à consonance vaguement familière) dont j'avais vraiment besoin lorsque je cherchais @properties
sur NSStrings
. Merci Axel.
Pour ceux qui le recherchent, la documentation d'Apple sur les attributs de propriété est ici .
Après avoir lu tant d'articles, SO posts et créé des applications de démonstration pour vérifier les attributs des propriétés variables, j'ai décidé de rassembler toutes les informations sur les attributs
voici donc le lien détaillé de l'article où vous pouvez trouver tous les attributs mentionnés ci-dessus, qui vous aideront avec défi. Un grand merci à toutes les personnes qui donnent les meilleures réponses ici !!
Exemple:
@property (nonatomic, retain) NSString *name;
@synthesize name;
Exemple:
@property (nonatomic, assign) NSString *address;
@synthesize address;
Google Objective-C Style Guide couvre assez bien cela:
Les setters prenant une NSString doivent toujours copier la chaîne acceptée. Ne conservez jamais simplement la chaîne. Cela évite à l'appelant de le changer sous vous à votre insu. Ne supposez pas cela parce que vous acceptez une NSString que ce n'est pas réellement une NSMutableString.
Serait-il regrettable que votre classe ait cet objet chaîne et qu'il disparaisse ensuite sous lui? Vous savez, comme la deuxième fois que votre classe mentionne cet objet, il a été désalloué par un autre objet?
C'est pourquoi vous souhaitez utiliser la sémantique de setter retain
.