web-dev-qa-db-fra.com

Différence entre _ et soi. en Objective-C

Existe-t-il une différence entre utiliser le trait de soulignement et utiliser le mot clé self dans Objective-C lors de l'appel d'un @property?

Déclaration de propriété:

@property (weak, nonatomic) NSString *myString;

En appelant @synthesize sur la propriété:

@synthesize myString = _myString;

Y a-t-il une différence si je veux l'utiliser dans mon code? Quand? Dans le getter/setter?

self.myString = @"test";
_myString = @"test";
48
Jakub

self.myString = @"test"; est exactement équivalent à écrire [self setMyString:@"test"];. Les deux appellent une méthode.

Vous auriez pu écrire cette méthode vous-même. Cela pourrait ressembler à quelque chose comme ça:

- (void)setMyString:(NSString*)newString
{
    _myString = newString;
}

Étant donné que vous avez utilisé @synthesize, vous n'avez pas à écrire cette méthode, vous pouvez simplement permettre au compilateur de l'écrire pour vous.

Ainsi, en regardant cette méthode, il semble que son appel fera exactement la même chose que d'affecter une valeur à la variable d'instance, non? Eh bien, ce n'est pas si simple.

Tout d'abord, vous pouvez écrire votre propre méthode de définition. Si vous le faites, votre méthode sera appelée et pourra faire toutes sortes de choses supplémentaires en plus de définir la variable. Dans ce cas, utiliser self.myString = appellera votre méthode, mais _myString = ne le ferait pas et des fonctionnalités différentes seraient donc utilisées.

Deuxièmement, si vous utilisez Key Value Observing, le compilateur exécute des astuces très astucieuses. En coulisse, il sous-classe votre classe et redéfinit votre méthode de définition (que vous l'ayez écrite vous-même ou générée par synthétiser), afin de faire les appels à willChangeValueForKey: nécessaires au bon fonctionnement de Key Value Observer. Vous n'avez pas besoin de savoir comment cela fonctionne (bien que ce soit très intéressant si vous voulez lire au lit!), Mais vous devez savoir que si vous voulez que l'observation de la valeur clé fonctionne automatiquement, vous devez utiliser les méthodes de définition.

Troisièmement, l'appel de la méthode de définition même si vous comptez sur la synthèse pour en écrire une vous offre une flexibilité pour l'avenir. Vous voudrez peut-être faire quelque chose de plus chaque fois qu'une valeur est modifiée, et au moment où vous découvrez que vous voulez le faire, vous pouvez écrire manuellement une méthode de définition. Si vous avez l'habitude d'utiliser toujours self.myString =, vous ne le ferez pas. besoin de changer le reste de votre code pour commencer à appeler la nouvelle méthode!

Quatrièmement, il en va de même pour les sous-classes. Si quelqu'un d'autre sous-classe votre code, si vous utilisez les paramètres, ils peuvent les remplacer pour ajuster les fonctionnalités.

Chaque fois que vous accédez directement à la variable d'instance, vous ne fournissez explicitement aucun moyen d'ajouter des fonctionnalités supplémentaires à ce stade. Étant donné que vous ou une autre personne voudrez peut-être utiliser de telles fonctionnalités à l'avenir, il est préférable d'utiliser les réglages en tout temps, à moins d'une bonne raison de ne pas le faire.

72
Amy Worrall

Vous avez raison - la première version (self.myString) appelle le getter/setter synthétisé et la seconde version accède directement à la variable membre privé.

On dirait que vous utilisez ARC, alors dans ce cas, cela ne fait pas une grande différence. Toutefois, si vous n'utilisez pas ARC, cela peut faire la différence, car l'affectation directe au membre privé ne déclenchera pas la logique de conservation/libération ou de copie/libération automatique générée pour vous à l'aide de synthesize.

9
Eric Petroelje

Le _ (trait de soulignement) est simplement une convention, comme expliqué dans cette question .

Lorsque vous ne préfixez pas l'accès à une propriété avec self., vous accédez directement à la variable sous-jacente, comme dans c struct. En règle générale, vous ne devez le faire que dans vos méthodes init et dans les accesseurs de propriétés personnalisées. Cela permet à des éléments tels que les propriétés calculées et KVC de fonctionner comme prévu.

3
Gil

Il y a un conseil à ne pas mentionner, l'accès par le soulignement est plus rapide et l'accès par soi-même est plus sûr (KVC). Peut-être que cela peut résumer le moment où vous devez utiliser chacun d'eux.

0
JFCa