Propriété NSSsortingng: copier ou conserver?

Disons que j’ai une classe appelée SomeClass avec un nom de propriété ssortingng :

 @interface SomeClass : NSObject { NSSsortingng* name; } @property (nonatomic, retain) NSSsortingng* name; @end 

Je comprends que ce nom peut être NSMutableSsortingng à un NSMutableSsortingng auquel cas cela peut entraîner un comportement erroné.

  • Pour les chaînes en général, est-ce toujours une bonne idée d’utiliser l’atsortingbut de copy au lieu de retain ?
  • Une propriété “copiée” est-elle moins efficace qu’une propriété “conservée”?

Pour les atsortingbuts dont le type est une classe de valeurs immuable conforme au protocole NSCopying , vous devez presque toujours spécifier copy dans votre déclaration @property . Spécifier retain est quelque chose que vous ne voulez presque jamais dans une telle situation.

Voici pourquoi vous voulez faire cela:

 NSMutableSsortingng *someName = [NSMutableSsortingng ssortingngWithSsortingng:@"Chris"]; Person *p = [[[Person alloc] init] autorelease]; p.name = someName; [someName setSsortingng:@"Debajit"]; 

La valeur actuelle de la propriété Person.name sera différente selon que la propriété est déclarée retain ou copy – ce sera @"Debajit" si la propriété est marquée retain , mais @"Chris" si la propriété est marquée comme copy .

Étant donné que dans presque tous les cas, vous souhaitez empêcher la mutation des atsortingbuts d’un object dans son dos, vous devez marquer les propriétés qui les représentent. (Et si vous écrivez vous-même le setter au lieu d’utiliser @synthesize n’oubliez pas d’utiliser réellement copy au lieu de le retain .)

La copie doit être utilisée pour NSSsortingng. Si c’est Mutable, alors il est copié. Si ce n’est pas le cas, alors il est juste retenu. Exactement la sémantique que vous voulez dans une application (laissez le type faire ce qu’il y a de mieux).

Pour les chaînes en général, est-ce toujours une bonne idée d’utiliser l’atsortingbut de copie au lieu de conserver?

Oui – en général, utilisez toujours l’atsortingbut de copie.

Cela est dû au fait que votre propriété NSSsortingng peut être transmise par une instance NSSsortingng ou une instance NSMutableSsortingng. Par conséquent, nous ne pouvons pas vraiment déterminer si la valeur transmise est un object immuable ou mutable.

Une propriété “copiée” est-elle moins efficace qu’une propriété “conservée”?

  • Si une propriété NSSsortingng est transmise à votre propriété, la réponse est ” Non ” – la copie n’est pas moins efficace que conserver.
    (Ce n’est pas moins efficace car le NSSsortingng est suffisamment intelligent pour ne pas réellement effectuer de copie.)

  • Si votre propriété reçoit une instance NSMutableSsortingng, la réponse est ” Oui ” – la copie est moins efficace que la conservation.
    (C’est moins efficace car une allocation et une copie réelles de la mémoire doivent avoir lieu, mais c’est probablement une chose souhaitable.)

  • D’une manière générale, une propriété “copiée” a le potentiel d’être moins efficace – cependant, grâce à l’utilisation du protocole NSCopying , il est possible d’implémenter une classe “aussi efficace” à copier qu’à conserver. Les instances NSSsortingng en sont un exemple.

Généralement (pas seulement pour NSSsortingng), quand dois-je utiliser “copier” au lieu de “conserver”?

Vous devez toujours utiliser copy lorsque vous ne souhaitez pas que l’état interne de la propriété change sans avertissement. Même pour les objects immuables – les objects immuables correctement écrits gèrent efficacement la copie (voir la section suivante concernant l’immuabilité et NSCopying ).

Il peut y avoir des raisons de performances pour retain objects, mais cela implique 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 que mon cours était immuable – ne puis-je pas simplement le “retenir”?

copy non utilisée. Si votre classe est vraiment immuable, il est préférable d’implémenter le protocole NSCopying pour que votre classe se retourne lorsque la copy est utilisée. Si tu fais ça:

  • Les autres utilisateurs de votre classe bénéficieront des avantages de la performance lorsqu’ils utilisent la copy .
  • L’annotation de copy rend votre propre code plus facile à entretenir – l’annotation de copy indique que vous n’avez vraiment pas besoin de vous soucier du changement d’état de cet object ailleurs.

J’essaie de suivre cette règle simple:

  • Est-ce que je veux conserver la valeur de l’object au moment où je l’affecte à ma propriété? Utilisez la copie

  • Est-ce que je veux conserver l’ object et je me fiche de ses valeurs internes actuelles ou futures? Utilisez fort (conservez).

Pour illustrer ceci: Est-ce que je veux conserver le nom “Lisa Miller” ( copie ) ou je veux conserver la personne de Lisa Miller ( forte )? Son nom pourrait changer plus tard en “Lisa Smith”, mais elle sera toujours la même personne.

Grâce à cet exemple, la copie et la conservation peuvent être expliquées comme suit:

 NSMutableSsortingng *someName = [NSMutableSsortingng ssortingngWithSsortingng:@"Chris"]; Person *p = [[[Person alloc] init] autorelease]; p.name = someName; [someName setSsortingng:@"Debajit"]; 

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

une nouvelle copie sera créée pour la chaîne [Person name] qui contiendra le contenu de la chaîne someName . Désormais, toute opération sur someName chaîne someName n’aura aucun effet sur [Person name] .

[Person name] et someName auront des adresses mémoire différentes.

Mais en cas de retenue,

le [Person name] contiendra la même adresse mémoire que celle de la chaîne nom, seule la chaîne de retenue du nombre sera incrémentée de 1.

Ainsi, tout changement de chaîne de nom sera répercuté dans la chaîne [Person name] .

Certes, mettre ‘copy’ sur une déclaration de propriété est en contradiction avec l’utilisation d’un environnement orienté object dans lequel les objects du tas sont passés par référence – l’un des avantages est que, lors de la modification d’un object, toutes les références à cet object voir les derniers changements. Un grand nombre de langues fournissent des mots-clés «ref» ou similaires pour permettre aux types de valeur (c’est-à-dire aux structures de la stack) de bénéficier du même comportement. Personnellement, j’utiliserais copie avec parcimonie, et si je pensais qu’une valeur de propriété devait être protégée des modifications apscopes à l’object à partir duquel elle était assignée, je pourrais appeler la méthode de copie de cet object pendant l’assignation, par exemple:

 p.name = [someName copy]; 

Bien sûr, lors de la conception de l’object qui contient cette propriété, vous seul saurez si la conception bénéficie d’un modèle où les affectations prennent des copies – Cocoawithlove.com a le texte suivant:

“Vous devez utiliser un accesseur de copie lorsque le paramètre setter peut être modifiable, mais vous ne pouvez pas modifier l’état interne d’une propriété sans avertissement ” – vous devez donc vous demander si vous pouvez changer la valeur de manière inattendue. Imaginez ce scénario:

 //person object has details of an individual you're assigning to a contact list. Contact *contact = [[[Contact alloc] init] autorelease]; contact.name = person.name; //person changes name [[person name] setSsortingng:@"new name"]; //now both person.name and contact.name are in sync. 

Dans ce cas, sans utiliser la copie, notre object contact prend automatiquement la nouvelle valeur; si nous l’utilisions, cependant, nous devrions nous assurer manuellement que les modifications ont été détectées et synchronisées. Dans ce cas, conserver la sémantique pourrait être souhaitable; dans un autre, la copie pourrait être plus appropriée.

 @interface TTItem : NSObject @property (nonatomic, copy) NSSsortingng *name; @end { TTItem *item = [[TTItem alloc] init]; NSSsortingng *test1 = [NSSsortingng ssortingngWithFormat:@"%d / %@", 1, @"Go go go"]; item.name = test1; NSLog(@"-item.name: point = %p, content = %@; test1 = %p", item.name, item.name, test1); test1 = [NSSsortingng ssortingngWithFormat:@"%d / %@", 2, @"Back back back"]; NSLog(@"+item.name: point = %p, content = %@, test1 = %p", item.name, item.name, test1); } Log: -item.name: point = 0x9a805a0, content = 1 / Go go go; test1 = 0x9a805a0 +item.name: point = 0x9a805a0, content = 1 / Go go go, test1 = 0x9a84660 

Vous devez utiliser copy tout le temps pour déclarer la propriété NSSsortingng

 @property (nonatomic, copy) NSSsortingng* name; 

Vous devriez lire ces informations pour savoir si elle renvoie une chaîne immuable (si une chaîne mutable a été transmise) ou si elle renvoie une chaîne conservée (si une chaîne immuable a été transmise)

NSCopying Protocol Reference

Implémentez NSCopying en conservant l’original au lieu de créer une nouvelle copie lorsque la classe et son contenu sont immuables

Objets Valeur

Donc, pour notre version immuable, nous pouvons simplement faire ceci:

 - (id)copyWithZone:(NSZone *)zone { return self; } 

Si la chaîne est très volumineuse, alors la copie affectera les performances et deux copies de la grande chaîne utiliseront davantage de mémoire.

Puisque name est un (immuable) NSSsortingng , copier ou conserver ne fait aucune différence si vous définissez un autre NSSsortingng pour le nommer. En d’autres termes, la copie se comporte comme conserver, augmentant le nombre de références de un. Je pense que c’est une optimisation automatique pour les classes immuables, car elles sont immuables et n’ont pas besoin d’être clonées. Mais si un NSMutalbeSsortingng mstr est défini sur name, le contenu de mstr sera copié pour des raisons de précision.