2017-07-15 1 views
1

J'apprends le langage de programmation Swift et pendant ce temps je suis parfois en contact avec l'ancien langage de programmation Objective-C et son code. Je suis absolument débutant et j'ai donc quelques questions pour mieux comprendre le Setter et le Getter. Donc, je sais que je peux créer une variable d'instance à travers des accolades dans le fichier .h mais normalement j'utilise des propriétés. Ces propriétés sont soutenues par une variable d'instance et offrent automatiquement une méthode Getter and Setter.Objective-C: Surcharge Getter & Setter avec Variable d'Instance (using _)

Exemple:

Véhicule .h fichier:

@interface Vehicle : NSObject 
@property int myProperty; 
@end 

Parce que je créé cette propriété je ne pas déclarer une méthode getter et setter dans le fichier vehicle.m parce qu'ils sont créé automatiquement par le compilateur. Je peux donc créer un véhicule-objet, définir et obtenir la valeur.

Exemple

main.m

Vehicle *myvehicle = [[vehicle alloc] init]; 
[myvehicle myProperty] // myvehicle.myProperty 
[myvehicle setMyProperty : 10] // myvehicle.myProperty = 10; 

Maintenant, je lis qu'il est possible de remplacer la méthode getter et setter créé automatiquement de ma propriété créé "myProperty". Lorsque je déclare ma propre version du Getter and Setter, je dois déclarer deux méthodes dans le fichier vehicle.h et vehicle.m. Dans le fichier vehicle.m, je n'appelle pas l'objet en utilisant le mot-clé self mais en utilisant sa variable d'instance créée automatiquement (_myProperty). Est ce bien?

Je l'ai essayé mais je reçois toujours une erreur et je ne sais pas pourquoi et à quoi ça sert.

Exemple

Véhicule .h:

@interface Vehicle : NSObject 
@property int myProperty; 
-(int) myProperty; //my new Getter method 
-(void) setMyProperty: (int)updatedMyProperty; //My new Setter method 
@end 

fichier .m du véhicule:

@implementation Vehicle 

    -(int) myProperty { 
     if (! _myProperty) { 
     _myProperty = NO; 
    } 
     return _myProperty; 
    } 

    -(void) setMyProperty: (int)updatedMyProperty { 
    if (_myProperty == updatedMyProperty) return; 
    _myProperty = updatedMyProperty; 
    } 
    @end 

je reçois toujours l'erreur "Utilisation d'identificateur non déclaré" et je n » Je sais pourquoi. Si je comprends bien, je n'ai pas besoin de déclarer l'ivar ou son nom en utilisant @synthesize car le compilateur crée automatiquement l'ivar appelé _myProperty pour moi. Je dois juste utiliser @synthesize quand je veux changer le nom de l'ivar.

Je ne suis pas sûr de savoir pourquoi je suis coincé et quel est le point. Pourriez-vous l'expliquer? Merci d'avance!

+0

non apparentés, mais surtout vous avez '[myvehicle setMyProperty = 10] '. Clairement, cela devrait être '[myvehicle setMyProperty: 10]'. – Rob

Répondre

0

Si vous implémentez toutes les méthodes d'accès, le compilateur ne synthétisera plus automatiquement l'ivar pour vous. Dans ce cas, vous devez le faire explicitement vous-même. Par exemple. Ceci n'est nécessaire que lorsque vous avez implémenté manuellement toutes les méthodes d'accès. La raison en est que le compilateur est assez intelligent pour savoir que si vous prenez en charge les méthodes d'accès, vous n'aurez peut-être pas besoin de l'ivar, à savoir que vous pourriez faire quelque chose de radicalement différent, par exemple.calculer les valeurs d'une autre propriété, définir/obtenir des valeurs depuis un magasin différent, etc. Vous pouvez souhaiter que le compilateur synthétise l'ivar (auquel cas vous ajoutez l'instruction @synthesize ci-dessus), mais il est tout aussi probable que vous ayez implémenté l'accesseur méthodes car aucun support ivar n'est nécessaire (dans ce cas, vous omettez l'instruction @synthesize ci-dessus).

Quoi qu'il en soit, rester avec votre exemple simple, vous obtenez quelque chose comme:

@interface Vehicle : NSObject 
@property (nonatomic) int myProperty; // if you don't write atomic accessor methods, you really should be explicit that this is nonatomic 

// as an aside, even if you implement accessor methods, you don't have to declare them here 
// 
// -(int) myProperty; //my new Getter method 
// -(void) setMyProperty: (int)updatedMyProperty; //My new Setter method 

@end 

Et

@implementation Vehicle 

// since you implemented all of the accessor properties, you have to manually synthesize the ivar 

@synthesize myProperty = _myProperty; 

- (int) myProperty { 
    // do whatever you want here; note, the following doesn't make sense 
    // 
    // if (! _myProperty) { 
    //  _myProperty = NO; 
    // } 

    return _myProperty; 
} 

- (void)setMyProperty:(int)updatedMyProperty { 
    if (_myProperty == updatedMyProperty) return; 
    _myProperty = updatedMyProperty; 
} 
@end 

De toute évidence, il n'y a pas de point par écrit ces méthodes accesseurs particulières dans l'exemple ci-dessus, parce que vous n'offre aucune nouvelle fonctionnalité, donc vous ne le feriez pas. Vous utiliseriez simplement les méthodes d'accesseurs auto-synthétisées. Mais dans les cas où vous avez vraiment besoin d'écrire vos propres méthodes d'accès, vous devez indiquer explicitement au compilateur si vous avez besoin de lui pour synthétiser l'ivar pour vous aussi ou non.

+0

Merci d'avoir aidé et répondu Rob! Cela m'a vraiment aidé à comprendre pourquoi et ce qui se passe dans les coulisses. Le fait que je doive synthétiser manuellement mon ivar en remplaçant le getter et le setter n'a pas été déclaré dans le livre que j'utilise. Donc, pour résumer: Dans la plupart des cas, je n'ai rien à synthétiser. Si je veux surcharger un, getter ou setter parce que je veux implémenter plus de code, je n'ai rien à faire de surcharger. Si je veux passer outre les deux, je dois synthétiser l'ivar manuellement mais comme je l'ai déjà dit dans la plupart des cas, il n'est pas nécessaire de le faire. Merci encore! – Ari

-1

Si vous utilisez l'attribut nonatomic, vous pouvez écraser soit getter ou setter ou les deux. le compilateur s'occupera du reste.

@property (nonatomic) int yourInt; 

puis écrire getter ou setter dans le fichier .m

-(int)yourInt 
{ 
// do something 
return _yourInt; 
} 

-(void)setYourInt:(int)someInt 
{ 
// do something 
_yourInt = someInt; 
} 

une note à la différence de ceux-ci:

_yourInt; //access variable directly 
[self yourInt]; // use getter method 

_yourInt = 4; // set vsriable directly 
[self setYourInt:4]; // use setter method 
+0

Je n'ai pas voté en bas, mais deux choses: Premièrement, la méthode 'getYourInt' devrait être' yourInt'. Objective-C n'utilise pas le préfixe 'get' pour les getters comme vous le voyez dans d'autres langues. En fait, cette faute de frappe est la seule raison pour laquelle votre exemple pourrait fonctionner, car vous n'avez pas réussi à implémenter toutes les méthodes d'accesseur et Xcode ne fait que contourner la synthèse d'ivar lorsque vous avez implémenté toutes les méthodes d'accesseur. Deuxièmement, la spécification de 'atomic' n'est pas pertinente. (En fait, quand vous omettez le qualificatif d'atomicité, 'atomic' est supposé.) – Rob

+0

merci pour clarifier! –

+0

Bien. Mais le problème est maintenant que vous avez correctement implémenté 'yourInt' et' setYourInt', l'ivar, '_yourInt', ne sera plus automatiquement synthétisé pour vous. En fait, c'est la question OP, à savoir, pourquoi il n'est pas synthétisé automatiquement. – Rob