Objective-C synthétisent nom de la propriété remplaçant
-
25-09-2019 - |
Question
Je suis en train de comprendre le but de la directive synthesize
avec dépassement du nom de la propriété. Dire que j'ai une interface définie comme suit:
@interface Dummy ... {
UILabel *_dummyLabel;
}
@property (retain, nonatomic) UILabel *dummyLabel;
Et dans le fichier de mise en œuvre, je:
@synthesize dummyLabel = _dummyLabel;
D'après ce que je comprends, "dummyLabel" est juste un alias de la variable d'instance "_dummyLabel". Est-il une différence entre self._dummyLabel et self.dummyLabel?
La solution
Oui. self._dummyLabel
est non défini, mais _dummyLabel
est pas.
syntaxe Dot se développe vers des invocations simples de la méthode, il est donc pas spécifique aux propriétés. Si vous avez une méthode appelée -(id)someObject
, par exemple dans le cas de object.someObject
, ce sera comme si vous avez écrit [object someObject];
.
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
Autres conseils
Votre compréhension est incorrecte. dummyLabel
est le nom de la propriété, et est pas un alias pour la variable d'instance - la variable d'instance est uniquement appelé _dummyLabel
. Donc, ce qui suit est une instance de Dummy
appelé myObject
:
-
[myObject dummyLabel]
fonctionne -
myObject.dummyLabel
fonctionne -
[myObject _dummyLabel]
échoue -
myObject._dummyLabel
échoue -
myObject->dummyLabel
échoue -
myObject->_dummyLabel
dépend de la visibilité du Ivar (@public
,@private
,@protected
) -
[myObject valueForKey: @"dummyLabel"]
fonctionne -
[myObject valueForKey: @"_dummyLabel"]
dépend de la mise en œuvre de+accessInstanceVariablesDirectly
(à savoir qu'il fonctionne dans le cas par défaut où retourne+accessInstanceVariablesDirectly
YES
).
L'avantage d'avoir un autre nom pour la Ivar que pour la propriété est que vous pouvez facilement voir dans le code lorsque vous accédez à un ou autre - Andre K
Je ne suis pas en mesure de trouver un bouton « commentaire » alors je vais avoir à poster comme une « réponse ».
Je voulais juste développer sur le commentaire d'André - en sachant quand vous utilisez les propriétés de synthèse contre la variable de vanille, vous savez (surtout en cas de setters) lorsqu'une variable est conservée / copiés / libérés automatiquement grâce à votre beau setter , vs être manipulé par la main.
Bien sûr, si vous faites les choses, vous ne avez probablement pas besoin de l'aide d'un poseur de conserver / libération des objets correctement! Mais il peut y avoir d'autres scénarios trop où se référant à vos Ivars comme self.ivar
au lieu de _ivar
peut être utile, par exemple lorsque vous utilisez setters personnalisés / getters au lieu de ceux par défaut de synthèse. Peut-être que chaque fois que vous modifiez une propriété, vous souhaitez aussi stocker à NSUserDefaults. Donc, vous pourriez avoir un code comme ceci:
@interface SOUserSettings : NSObject {
BOOL _autoLoginOn;
}
@property (nonatomic, assign) BOOL autoLoginOn;
@end
@implementation SOUserSettings
@synthesize autoLoginOn = _autoLoginOn;
- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {
_autoLoginOn = newAutoLoginOnValue;
[[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"];
}
@end
Note: Ceci est juste un code d'illustration, il pourrait y avoir mille choses mal avec elle
Alors maintenant, dans votre code, si vous avez une ligne qui dit _autoLoginOn = YES
-. Vous savez que ça ne va pas être sauvé à NSUserDefaults, alors que si vous utilisez self.autoLoginOn = YES
vous savez exactement ce qui va se passer
La différence entre _autoLoginOn
et self.autoLoginOn
est plus que sémantique.
Je ne vois pas de gros avantage de renommer _dummyLabel à dummyLabel
Dans certains runtimes ObjC vous avez du mal à faire des variables d'instance invisible pour les utilisateurs de la classe. Pour les coller certains préfixe (ou suffixe) sur vos variables d'instance peut préciser (ou plus clair) que vous ne voulez pas que quelqu'un de jouer avec vos variables. Cependant, vous ne voulez pas que vos gunk fonctions publiques. Cela vous permet de l'enlever.
Il pourrait également être utile si vous avez besoin de maintenir une ancienne interface avec un ensemble de noms en même temps que d'une nouvelle série d'API avec une nouvelle série de noms (setLastname contre setSurname).
Ancien poste, mais je pense qu'il est important de mentionner qu'il est recommandé d'accéder à des variables via des accesseurs (donc, avec la notation par points). L'accès est fortement recommandé directement un champ (_ivar) seulement quand initialisant.
Il y a l'article de quelques bonnes d'Apple: https://developer.apple.com/ bibliothèque / ios / # documentation / cacao / conceptuel / ProgrammingWithObjectiveC / EncapsulatingData / EncapsulatingData.html
Au dernier paragraphe:
Vous devriez toujours accéder directement aux variables d'instance de l'intérieur une méthode d'initialisation, car au moment où une propriété est définie, la reste de l'objet ne peut pas encore être complètement initialisé. Même si vous ne fournissent pas des méthodes d'accès personnalisé ou connaissez des effets secondaires de au sein de votre propre classe, une sous-classe future peut passer outre très bien la comportement.