web-dev-qa-db-fra.com

Les propriétés déclarées nécessitent-elles une variable d'instance correspondante?

Les propriétés d'Objective-C 2.0 nécessitent-elles la déclaration d'une variable d'instance correspondante? Par exemple, j'ai l'habitude de faire quelque chose comme ça:

MonObjet.h

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

MonObjet.m

@implementation
@synthesize name;
@end

Cependant, si je faisais cela à la place:

MonObjet.h

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

Est-ce toujours valable? Et est-ce en quelque sorte différent de mon exemple précédent?

102
indragie

Si vous utilisez le Modern Objective-C Runtime (c'est-à-dire iOS 3.x ou supérieur, ou Snow Leopard 64 bits ou supérieur), vous le faites pas doivent définir des ivars pour vos propriétés dans des cas comme celui-ci.

Quand vous @synthesize la propriété, l'ivar sera en effet synthétisé également pour vous. Cela contourne le scénario de l'ivar fragile. Vous pouvez en savoir plus à ce sujet sur Cocoa with Love

94
jbrennan

Dans votre interface, vous pouvez déclarer formellement une variable d'instance entre les accolades, ou via @property En dehors des accolades, ou les deux. De toute façon, ils deviennent des attributs de la classe. La différence est que si vous déclarez @property, Vous pouvez implémenter en utilisant @synthesize, Qui code automatiquement votre getter/setter pour vous. Le setter auto-codeur initialise les entiers et flotte à zéro, par exemple. SI vous déclarez une variable d'instance, et NE spécifiez PAS de @property Correspondant, vous ne pouvez pas utiliser @synthesize Et must écrire votre propre getter/setter.

Vous pouvez toujours remplacer le getter/setter auto-codé en spécifiant le vôtre. Cela se fait généralement avec la propriété managedObjectContext qui est chargée paresseusement. Ainsi, vous déclarez votre managedObjectContext en tant que propriété, mais vous écrivez également une méthode -(NSManagedObjectContext *)managedObjectContext. Rappelons qu'une méthode, qui porte le même nom qu'une variable/propriété d'instance est la méthode "getter".

La méthode de déclaration @property Vous permet également d'autres options, telles que retain et readonly, ce que la méthode de déclaration de variable d'instance ne permet pas. Fondamentalement, ivar est l'ancienne méthode, et @property Le prolonge et le rend plus sophistiqué/plus facile. Vous pouvez vous référer à l'utilisation de soi. préfixe ou non, peu importe tant que le nom est unique à cette classe. Sinon, si votre superclasse a le même nom de propriété que vous, alors vous devez dire comme self.name ou super.name afin de spécifier de quel nom vous parlez.

Ainsi, vous verrez de moins en moins de personnes déclarer ivars entre les accolades, et passer à la place en spécifiant simplement @property, Puis en faisant @synthesize. Vous ne pouvez pas faire @synthesize Dans votre implémentation sans un @property Correspondant. Le synthétiseur sait uniquement de quel type d'attribut il s'agit à partir de la spécification @property. L'instruction synthesize vous permet également de renommer des propriétés, afin que vous puissiez faire référence à une propriété par un nom (raccourci) à l'intérieur de votre code, mais à l'extérieur dans le fichier .h, utilisez le nom complet. Cependant, avec la saisie semi-automatique vraiment cool que XCode a maintenant, c'est moins un avantage, mais est toujours là.

J'espère que cela aide à dissiper toute la confusion et la désinformation qui flottent là-bas.

71
PapaSmurf

cela fonctionne dans les deux sens, mais si vous ne les déclarez pas entre accolades, vous ne verrez pas leurs valeurs dans le débogueur dans xcode.

8
rickm

Si vous utilisez XCode 4.4 ou une version ultérieure, il générera pour vous du code de synthèse de variable d'instance.

Il vous suffit de déclarer des propriétés comme ci-dessous; il générera pour vous du code de synthèse et une variable d'instance déclarant du code.

@property (nonatomic, strong) NSString *name;

il va générer du code de synthèse comme

@synthesize name = _name;

et vous pouvez accéder à la variable d'instance en utilisant _name, il est similaire à déclarer

NSString* _name

mais si vous déclarez une propriété en lecture seule,

@property (nonatomic, strong, readonly) NSString *name;

il va générer du code

@synthesize name;

ou

@synthesize name = name; 

Vous devez donc accéder au nom de la variable instantanée sans le préfixe "_" de quelque manière que vous puissiez écrire votre propre code de synthèse, puis le compilateur générera du code pour vous. tu peux écrire

@synthesize name = _name;
3
Shafraz Buhary

De la documentation:

En général, le comportement des propriétés est identique sur les environnements d'exécution modernes et hérités (voir "Versions et plates-formes d'exécution" dans le Guide de programmation d'exécution d'Objective-C). Il existe une différence clé: le runtime moderne prend en charge la synthèse des variables d'instance, contrairement au runtime hérité.

Pour que @synthesize fonctionne dans le runtime hérité, vous devez soit fournir une variable d'instance avec le même nom et le type compatible de la propriété, soit spécifier une autre variable d'instance existante dans l'instruction @synthesize. Avec le runtime moderne, si vous ne fournissez pas de variable d'instance, le compilateur en ajoute une pour vous.

3
Charlie Elliott

Le langage de programmation Objective-C: directives d'implémentation des propriétés

Il existe des différences dans le comportement de la synthèse des accesseurs qui dépendent du runtime (voir aussi "Différence d'exécution"):

  • Pour les runtimes hérités, les variables d'instance doivent déjà être déclarées dans le bloc @interface de la classe actuelle. S'il existe une variable d'instance du même nom que la propriété et si son type est compatible avec le type de la propriété, elle est utilisée, sinon vous obtenez une erreur de compilation.

  • Pour les runtimes modernes (voir "Versions et plates-formes d'exécution" dans le Guide de programmation d'Objective-C), les variables d'instance sont synthétisées selon les besoins. Si une variable d'instance du même nom existe déjà, elle est utilisée.

1
Nate