330 votes

Propriété NSString : copier ou conserver ?

Disons que j'ai une classe appelée SomeClass avec un string nom de la propriété :

@interface SomeClass : NSObject
{
    NSString* name;
}

@property (nonatomic, retain) NSString* name;

@end

Je comprends que le nom peut être attribué à un NSMutableString dans ce cas, cela peut conduire à un comportement erratique.

  • Pour les cordes en général, est-ce toujours une bonne idée d'utiliser le copy au lieu de l'attribut retain ?
  • Une propriété "copiée" est-elle en quelque sorte moins efficace qu'une propriété "conservée" ?

440voto

Chris Hanson Points 34485

Pour les attributs dont le type est une classe de valeurs immuables conforme à la directive NSCopying vous devez presque toujours spécifier copy dans votre @property déclaration. Spécifier retain est quelque chose que vous ne voulez presque jamais dans une telle situation.

Voici pourquoi vous voulez faire ça :

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

La valeur actuelle de la Person.name sera différente selon que la propriété est déclarée ou non. retain ou copy - il sera @"Debajit" si le bien est marqué retain pero @"Chris" si le bien est marqué copy .

Puisque dans presque tous les cas, vous voulez prévenir Si vous modifiez les attributs d'un objet dans son dos, vous devez marquer les propriétés qui les représentent. copy . (Et si vous écrivez vous-même le setter au lieu d'utiliser la fonction @synthesize vous devez vous rappeler d'utiliser réellement copy au lieu de retain en elle.)

120voto

Frank Krueger Points 27508

Copie doit être utilisé pour NSString. Si elle est Mutable, elle est copiée. S'il ne l'est pas, il est simplement conservé. C'est exactement la sémantique que vous voulez dans une application (laisser le type faire ce qui est le mieux).

66voto

TroyJ Points 838

Pour les chaînes de caractères en général, est-ce toujours une bonne idée d'utiliser l'attribut copy au lieu de retain ?

Oui, en général, utilisez toujours l'attribut "copy".

En effet, votre Propriété NSString peut recevoir un NSString instance ou un NSMutableString instance Par conséquent, nous ne pouvons pas vraiment déterminer si la valeur transmise est un objet immuable ou mutable.

Une propriété "copiée" est-elle en quelque sorte moins efficace qu'une propriété "conservée" ?

  • Si votre propriété passe un NSString instance la réponse est " Non "La copie n'est pas moins efficace que la conservation.
    (Ce n'est pas moins efficace car la NSString est suffisamment intelligente pour ne pas effectuer réellement une copie).

  • Si votre propriété passe un NSMutableString instance alors la réponse est " Oui " - la copie est moins efficace que la conservation.
    (C'est moins efficace car une allocation et une copie de mémoire réelle doivent avoir lieu, mais c'est probablement une chose souhaitable).

  • D'une manière générale, une propriété " copiée " est potentiellement moins efficace, mais grâce à l'utilisation de l'outil d'évaluation de l'efficacité énergétique, il est possible d'améliorer l'efficacité énergétique de la propriété. NSCopying il est possible d'implémenter une classe qui est "aussi efficace" pour la copie que pour la conservation. Instances NSString en sont un exemple.

De manière générale (pas seulement pour NSString), quand dois-je utiliser "copy" au lieu de "retain" ?

Vous devez toujours utiliser copy lorsque vous ne voulez pas que l'état interne de la propriété change sans avertissement. Même pour les objets immuables - les objets immuables correctement écrits gèreront la copie efficacement (voir la section suivante concernant l'immuabilité et l'intégrité de la propriété). NSCopying ).

Il peut y avoir des raisons de performance pour retain mais cela s'accompagne d'une surcharge de maintenance - vous devez gérer la possibilité que l'état interne change en dehors de votre code. Comme on dit - optimisez en dernier.

Mais, j'ai écrit ma classe pour qu'elle soit immuable - ne puis-je pas simplement la "retenir" ?

Non - utiliser copy . Si votre classe est vraiment immuable, il est préférable d'implémenter l'option NSCopying pour que votre classe se retourne elle-même lorsque copy est utilisé. Si vous faites cela :

  • Les autres utilisateurs de votre classe bénéficieront des mêmes avantages en termes de performances lorsqu'ils utiliseront l'option copy .
  • El copy rend votre propre code plus facile à maintenir - l'annotation copy indique que vous n'avez vraiment pas besoin de vous soucier du fait que cet objet change d'état ailleurs.

39voto

Johannes Fahrenkrug Points 12795

J'essaie de suivre cette règle simple :

  • Est-ce que je veux m'accrocher à la valeur de l'objet au moment où je l'assigne. à ma propriété ? Utilisez copie .

  • Est-ce que je veux m'accrocher à la objet y Je me fiche de ses valeurs internes sont actuellement ou seront dans le futur ? Utilisez fort (retenir).

Pour illustrer : Est-ce que je veux m'accrocher à la nombre "Lisa Miller" ( copie ) ou à je veux m'accrocher à la personne Lisa Miller ( fort ) ? Son nom pourrait plus tard devenir "Lisa Smith", mais elle sera toujours la même personne.

14voto

Divya Arora Points 51

Cet exemple permet d'expliquer la notion de "copier et conserver" :

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

si la propriété est de type copie alors ,

une nouvelle copie sera créée pour le [Person name] qui contiendra le contenu de someName ficelle. Maintenant, toute opération sur someName n'aura aucun effet sur [Person name] .

[Person name] y someName Les chaînes de caractères auront des adresses mémoire différentes.

Mais en cas de retenue,

les deux [Person name] contiendra la même adresse mémoire que celle de la chaîne somename, mais le nombre de retenue de la chaîne somename sera incrémenté de 1.

Ainsi, tout changement dans la chaîne de caractères d'un nom sera reflété dans [Person name] chaîne.

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