Quelle est la différence entre les ivars et les propriétés dans Objective-C?

Quelle est la différence sémantique entre ces 3 manières d’utiliser les ivars et les propriétés dans objective-c?

1.

@class MyOtherObject; @interface MyObject { } @property (nonatomic, retain) MyOtherObject *otherObj; 

2.

 #import "MyOtherObject.h" @interface MyObject { MyOtherObject *otherObj; } @property (nonatomic, retain) MyOtherObject *otherObj; 

3.

  #import "MyOtherObject.h" @interface MyObject { MyOtherObject *otherObj; } 

Le numéro 1 diffère des deux autres par une déclaration directe indiquant la classe MyOtherObject pour minimiser la quantité de code vue par le compilateur et l’éditeur de liens et également éviter les références circulaires. Si vous le faites de cette façon, n’oubliez pas de mettre le fichier #import dans le fichier .m.

En déclarant un @property (et un @synthesize correspondant dans le fichier .m), vous générez automatiquement des méthodes d’accesseur avec la sémantique de la mémoire gérée comme vous le spécifiez. La règle de base pour la plupart des objects est Retain, mais NSSsortingngs, par exemple, devrait utiliser Copy. Considérant que Singletons et Délégués doivent généralement utiliser Assign. L’accessoire d’écriture manuelle est fastidieux et sujet aux erreurs, ce qui permet d’économiser beaucoup de bogues et de dactylographie.

En outre, déclarer une propriété synthétisée vous permet d’appeler une méthode d’accesseur en utilisant la notation par points comme ceci:

 self.otherObj = someOtherNewObject; // set it MyOtherObject *thingee = self.otherObj; // get it 

Au lieu de la manière normale de transmettre les messages:

 [self setOtherObject:someOtherNewObject]; // set it MyOtherObject *thingee = [self otherObj]; // get it 

Dans les coulisses, vous appelez vraiment une méthode qui ressemble à ceci:

 - (void) setOtherObj:(MyOtherObject *)anOtherObject { if (otherObject == anOtherObject) { return; } MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second otherObject = [anOtherObject retain]; // put the new value in [oldOtherObject release]; // let go of the old object } // set it 

…ou ca

 - (MyOtherObject *) otherObject { return otherObject; } // get it 

Douleur totale dans les fesses, à droite. Maintenant, faites cela pour chaque ivar de la classe. Si vous ne le faites pas exactement, vous obtenez une fuite de mémoire. Il vaut mieux laisser le compilateur faire le travail.

Je vois que le numéro 1 n’a pas d’ivar. En supposant que ce ne soit pas une faute de frappe, c’est bien parce que les directives @property / @synthesize déclareront un ivar pour vous aussi, dans les coulisses. Je crois que c’est nouveau pour Mac OS X – Snow Leopard et iOS4.

Le numéro 3 n’a pas ces accesseurs générés, vous devez donc les écrire vous-même. Si vous voulez que vos méthodes d’accessoires aient des effets secondaires, vous faites votre danse standard de gestion de mémoire, comme indiqué ci-dessus, puis vous faites tout ce que vous devez faire, dans la méthode de l’accesseur. Si vous synthétisez une propriété et écrivez la vôtre , votre version est prioritaire.

Ai-je tout couvert?

Autrefois, vous aviez des ivars, et si vous vouliez laisser une autre classe définir ou les lire, vous deviez définir un getter (par exemple, -(NSSsortingng *)foo) et un setter (ie, -(void)setFoo:(NSSsortingng *)aFoo; ).

Quelles propriétés vous donne est le setter et getter gratuitement (presque!) Avec un ivar. Donc, lorsque vous définissez une propriété maintenant, vous pouvez définir l’atomicité (voulez-vous autoriser plusieurs actions de paramétrage à partir de plusieurs threads, par exemple), et affecter / conserver / copier la sémantique (c’est-à-dire ou tout simplement enregistrer la valeur actuelle – important si une autre classe tente de définir votre propriété de chaîne avec une chaîne mutable qui pourrait être modifiée ultérieurement.

C’est ce @synthesize fait @synthesize . Beaucoup de gens laissent le nom ivar de la même manière, mais vous pouvez le changer lorsque vous écrivez votre instruction synthesize (c’est-à-dire @synthesize foo=_foo; signifie créer une ivar nommée _foo pour la propriété foo , donc et vous n’utilisez pas self.foo , vous devrez utiliser _foo = ... – cela vous aide juste à attraper des références directes à l’ivar si vous voulez seulement passer par le setter et le getter).

A partir de Xcode 4.6, vous n’avez pas besoin d’utiliser l’instruction @synthesize – le compilateur le fera automatiquement et @synthesize par défaut le nom de l’ivar à _ .