Question

Quelle est la syntaxe correcte pour accéder à une variable d'instance en Objective-C?

Supposons que nous ayons cette variable:

@interface thisInterface : UIViewController {
    NSMutableString *aString;
}

@property (nonatomic, retain) NSMutableString *aString;

et qu'il est synthétisé.

Quand on veut accéder, nous avons d'abord voudrait allouer et initialiser. Ayant programmé en Objective-C pendant environ un mois, je l'ai vu deux différentes formes de syntaxe. J'ai vu des gens faire simplement aString = [[NSMutableString alloc] initWithString:@"hi"], où ils affectent la chaîne comme ça; J'ai aussi vu les gens commencent tout avec self.aString puis ils procèdent à initialiser leur Ivar. Je suppose que je suis juste essayer de comprendre ce qui est la façon la plus appropriée de l'initialisation d'une variable d'instance, car avec l'exemple précédent, j'ai reçu des erreurs de EXC_BAD_ACCESS de celui-ci. Après le préfixer self. cependant, il ne semble pas.

Pardonnez-moi si cela est une question en double, mais après avoir lu quelques messages sur SO, il m'a rendu curieux. Je suis en train d'apprendre la syntaxe correcte avec Objective-C parce que je préfère être propre plutôt que bâclée.

Était-ce utile?

La solution

Si vous avez déclaré une propriété et @synthesize dans le fichier .m, il vous suffit défini comme ceci:

self.aString = @"hi"; // or [[NSMutableString alloc] initWithString:@"hi"];

L'utilisation self.varName profite de ce que votre déclaration de propriété en fait does- il gère la rétention de la nouvelle valeur (depuis votre propriété a l'attribut retain), libérant l'ancienne valeur, etc pour vous.

Si vous faites juste:

aString = someValue;

... vous pouvez être une fuite de la valeur initiale, qui était en aString, puisque sans utiliser self.aString vous accédez à la variable directement vs par la propriété.

Autres conseils

Notez la différence entre self->varName et self.varName

La première est pointeur accès. La seconde est la propriété accès.

Pourquoi est-ce important? l'accès est direct pointeur. l'accès aux biens, aux autres marques de main utilisent des accesseurs (qu'ils soient ou non @synthesized). De plus, à titre de commodité, les accesseurs @synthesized prendre soin du mangement de mémoire pour vous (par exemple lors de l'utilisation self.varName = ...;), alors que varName = ...; ne fait que ce qu'il dit, à savoir l'affectation -> (il se trouve l'explication des erreurs EXC_BAD_ACCESS vous pourriez obtenir ).

Syntaxiquement, les deux formes sont correctes. Si vous voulez mieux communiquer l'intention, l'utilisation self->varName lorsque vous voulez travailler directement avec le pointeur et l'utilisation self.varName lorsque vous souhaitez profiter de la commodité de @property.

Voici toutes les combinaisons possibles (je pense) OKs et Bads ne sont correct lorsque la propriété de aString a attribut retain:

@property (nonatomic, retain) NSMutableString *aString;

1

aString = [[NSMutableString alloc] init]; //OK: 

Ceci est OK, mais seulement dans le aString cas ne pointe pas vers un objet non valide ou vous perdrez une référence à cet objet et il fuira parce que vous ne serez pas en mesure de l'atteindre pour le libérer.

2

aString = [NSMutableString string]; //BAD

Bad parce que vous êtes supposé conserver aString (comme vous déclarez cette façon), vous ne retenez pas et vous obtiendrez sûrement obtenir EXC_BAD_ACCESS dans l'avenir

3

aString = [[NSMutableString string] retain]; //OK

Identique à la première approche, que bon si aString ne pointe pas vers un objet valide. Cependant, je vais utiliser la première si.

4

aString = [[[NSMutableString alloc] init] autorelease];//BAD

Identique à la deuxième approche.

5

self.aString = [[NSMutableString alloc] init]; //BAD!!

Bad parce que vous retenons deux fois, par conséquent, il conduira à des fuites de mémoire

6

self.aString = [[NSMutableString string]; //******GOOD!******

Ceci est probablement le plus sûr. Il sera retenu par le poseur de propriété et puisque vous utilisez le poseur tout autre objet qui aurait pu être fait par aString sera publié de manière appropriée

7

self.aString = [[NSMutableString string] retain]; //BAD

est retenu deux fois.

8

self.aString = [[[NSMutableString alloc] init] autorelease];//Ok

est OK, mais j'utiliser la méthode pratique au lieu de cette longue approche:)

Méfiez-vous que les # 1 et # 3 options sont parfaitement bien si vous savez ce que vous faites. En fait, je les utilise beaucoup plus fréquemment que # 6

Personnellement, je préfère utiliser la syntaxe self.. Il fait juste de déterminer plus facilement que sa variable d'instance, et non pas seulement une autre variable dans le périmètre actuel qui sera perdu lorsque son NSAutoreleasePool est drainée. Cependant, il est bon de les utiliser dans les deux sens, et si vous recevez des erreurs de EXC_BAD_ACCESS, ce n'est pas parce que vous n'accédées sans l'aide self.. Vous avez raison de dire que vous devez alloc, et la façon que vous choisissez d'accéder à vos variables, gardez cohérente ou vous recevrez des erreurs.

J'espère que cette aide.

Utilisez toujours accesseurs sauf dans init, dealloc et dans accesseurs eux-mêmes. Faire cela vous permettra d'économiser beaucoup de maux de tête comme celui que vous décrivez. En outre, le nom de votre Ivars quelque chose de différent de votre propriété (_foo, foo_, mFoo, mais pas foo).

self.foo est exactement la même que [self foo]. J'appelle la méthode foo. self.foo = x est exactement la même un [self setFoo:x]. Il appelle la méthode setFoo:. Si vous synthétisé le foo de la propriété en tant que variable retain, alors ce ressemble à quelque chose comme:

@synthesize foo = foo_;

- (void)setFoo:(id)value {
  [value retain];
  [foo_ release];
  foo_ = value;
}

Cela libère correctement l'ancienne valeur de foo_, attribue un nouveau et le conserve.

foo = x (en supposant que foo est un ivar) ne remet pas de méthode. Aucun. Il attribue juste la valeur du pointeur dans x au pointeur dans foo. Si foo a quelque chose qui a été retenu, il est divulgué. Si la nouvelle valeur que vous assignons n'est pas conservé, vous brisez plus tard.

La solution est d'utiliser toujours accesseurs quand vous le pouvez.

Soit.

En utilisant la syntaxe de points est plus propre (pour certains) et il compile à l'équivalent. i.e. self.iVar est le même que [self iVar] et self.iVar = aValue est le même que [self setIVar:aValue];

self.aString est un sucre syntaxique à [self aString]. Synthétisent une propriété juste créer la méthode -aString et -setAString: (en fonction de la propriété que vous avez choisie sans le trivial afféterie).

Maintenant, la question est de savoir si d'utiliser la notation .. Je vous suggère de ne pas l'utiliser. Pourquoi? Sachez tout d'abord que Objective-C pour objectif d'être un simple ajout à C. Cela signifie que chaque code valide C est également un code Objective-C valide.

Maintenant, regardez ce qu'ils ont fait avec la notation de points. La dernière déclaration ne tient plus. Vous ne le distinguer un accès à un champ d'une structure de C et l'envoi de méthode objective-c.

Alors s'il vous plaît ne pas utiliser la notation de points. Préférez l'utilisation de [auto ..].

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top