web-dev-qa-db-fra.com

@property et @synthesize dans objective-c

Pendant que je jouais et découvrais comment les choses fonctionnent https://github.com/enormego/EGOTableViewPullRefresh j'ai trouvé mystérieux @property et @synthesize. Voici le code que j'ai mentionné

EGORefreshTableHeaderView.h

@interface EGORefreshTableHeaderView : UIView {
    id _delegate;
    EGOPullRefreshState _state;

    UILabel *_lastUpdatedLabel;
    UILabel *_statusLabel;
    CALayer *_arrowImage;
    UIActivityIndicatorView *_activityView;
}

@property(nonatomic,assign) id <EGORefreshTableHeaderDelegate> delegate;

EGORefreshTableHeaderView.m

@synthesize delegate=_delegate;

J'ai lu ceci http://developer.Apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html et d'après ce que je comprends, c'est créer un nouveau nom pour _délégué qui est délégué. (Ai-je raison de cette compréhension?)

Mais je ne comprends toujours pas pourquoi ils doivent compliquer les choses avec la directive @synthesize =.

19
sarunw

C'est vraiment compliqué, vraiment? C'est juste un peu de syntaxe qui vous permet de spécifier l'ivar que vous souhaitez utiliser pour sauvegarder la propriété pour laquelle vous dites au compilateur de créer des accesseurs. S'ils ne fournissaient pas ceci ou quelque chose d'équivalent, alors vous devriez toujours avoir vos noms de propriété correspondant à vos noms d'ivar, et il y a des raisons pour lesquelles vous ne voudrez peut-être pas cela.

Si vous n'avez pas besoin de nommer vos ivars différemment, vous n'avez pas à vous soucier de spécifier le nom de l'ivar. En fait, vous n'avez pas du tout à créer d'ivars pour vos propriétés ... sinon, le compilateur les créera pour vous.

Mise à jour: À partir du milieu de 2013, LLVM utilise par défaut la synthèse des accesseurs pour les propriétés, donc dans la plupart des cas, vous n'avez plus besoin de spécifier @synthesize du tout. Le seul cas où vous l'utiliseriez toujours est lorsque vous souhaitez sauvegarder la propriété avec une variable d'instance différente de celle que le compilateur générerait pour vous. En outre, le nom par défaut de l'ivar qui sauvegarde une propriété sera le nom de la propriété précédé d'un trait de soulignement. Ainsi, le code dans l'exemple de l'OP pourrait être simplifié en supprimant les lignes:

id _delegate;

et:

@synthesize delegate=_delegate;

J'ai supprimé mes conseils précédents contre l'utilisation d'un préfixe de soulignement car il était clairement en désaccord avec la mode actuelle et le comportement par défaut du compilateur. Pour autant que je sache, il est toujours difficile d'utiliser un préfixe de soulignement pour les noms de vos méthodes.

De plus, il est venu à mon attention qu'au moins une personne a interprété la première ligne de ma réponse, "C'est vraiment compliqué, vraiment?" comme condescendant. J'espère que ce n'était l'impression que d'une seule personne - je n'avais certainement pas l'intention de faire preuve de condescendance, mais j'essayais seulement de cadrer ma réponse autour de l'affirmation du PO que le @synthesize xxx=_xxx; la directive rend les choses compliquées. Il y a beaucoup à absorber lorsque vous débutez; nous espérons que le nouveau comportement "synthétiser par défaut" réduira le fardeau pour les nouveaux arrivants.

30
Caleb

Vous avez raison, en utilisant

@synthesize foobar=_foobar;

est un peu inutile dans la plupart des cas, mais à un niveau abstrait, il vous permet de renvoyer la valeur d'une autre variable entièrement. Un péché ...

@synthesize foobar=fluffybunny;

Permet d'obtenir ou de définir la valeur de fluffybunny chaque fois que vous utilisez l'accesseur .foobar

Cependant en termes de@synthesize complexité, préférez-vous écrire

-(void)setFoobar:(id)aobject {
    [self willSetValueForKey:"foobar"];
    id old = foobar;
    foobar = [aobject retain];
    [old release];
    [self didSetValueForKey:"foobar"];
}

-(id)foobar {
    [self willAccessValueForKey:"foobar"];
    id obj = [self primitiveValueForKey:@"foobar"];
    [self didAccessValueForKey:"foobar"];    
    return obj;
}

Ou

@synthesize foobar;

Ce n'est pas particulièrement bien écrit car j'ai oublié comment bien les faire, mais la directive @synthesize vous empêche d'avoir à écrire des accesseurs tant de fois. C'est l'une des choses qui a beaucoup sucé à propos d'Obj-C 1.0.

Code gratuit, ne le frappez pas.

17
Warren Burton