web-dev-qa-db-fra.com

Objective-C 101 (conserver vs affecter) NSString

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.

54
qstar

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).

68
Chuck

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.

19
Axel

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.

12
fbrereto

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.

9
jem

Pour ceux qui le recherchent, la documentation d'Apple sur les attributs de propriété est ici .

9
tbone

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

  1. atomique // par défaut
  2. non anatomique
  3. fort = conserver // par défaut
  4. faible = unsafe_unretained
  5. conserver
  6. assign // par défaut
  7. unsafe_unretained
  8. copie
  9. lecture seulement
  10. readwrite // par défaut

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 !!

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

  1. retenir = fort
    • il est conservé, l'ancienne valeur est libérée et elle est affectée
    • conserver spécifie que la nouvelle valeur doit être envoyée - conserver lors de l'affectation et l'ancienne valeur envoyée - relâcher
    • conserver est le même que fort.
    • Apple dit que si vous écrivez, il sera automatiquement converti/fonctionnera comme fort uniquement.
    • des méthodes comme "alloc" incluent un "retenir" implicite

Exemple:

@property (nonatomic, retain) NSString *name;

@synthesize name;
  1. assigner
    • 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 C et faible pour les références faibles aux objets Objective-C.

Exemple:

@property (nonatomic, assign) NSString *address;

@synthesize address;
8
swiftBoy

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.

3
funroll

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.

2
Dan Ray