web-dev-qa-db-fra.com

@synthesize vs @dynamic, quelles sont les différences?

Quelles sont les différences entre implémenter un @property avec @dynamic ou @synthesize?

549
nico

@synthesize générera des méthodes getter et setter pour votre propriété. @dynamic indique simplement au compilateur que les méthodes getter et setter ne sont pas implémentées par la classe elle-même mais ailleurs (comme la superclasse ou seront fournies au moment de l'exécution).

Les utilisations pour @dynamic sont par exemple avec des sous-classes de NSManagedObject (CoreData) ou lorsque vous souhaitez créer une sortie pour une propriété définie par une superclasse non définie en tant que sortie.

@dynamic peut également être utilisé pour déléguer la responsabilité de la mise en œuvre des accesseurs. Si vous implémentez vous-même les accesseurs dans la classe, vous n'utilisez normalement pas @dynamic.

Super classe:

@property (nonatomic, retain) NSButton *someButton;
...
@synthesize someButton;

Sous-classe:

@property (nonatomic, retain) IBOutlet NSButton *someButton;
...
@dynamic someButton;
730
diederikh

Jetez un oeil à cet article ; sous la rubrique "Méthodes fournies à l'exécution":

Certains accesseurs sont créés de manière dynamique au moment de l'exécution, tels que certains utilisés dans la classe NSManagedObject de CoreData. Si vous souhaitez déclarer et utiliser des propriétés pour ces cas, mais que vous souhaitez éviter les avertissements concernant les méthodes manquantes au moment de la compilation, vous pouvez utiliser la directive @dynamic à la place de @synthesize.

...

L'utilisation de la directive @dynamic indique essentiellement au compilateur "ne vous inquiétez pas, une méthode est sur le chemin".

En revanche, la directive @synthesize génère les méthodes d’accesseur à la compilation (bien que, comme indiqué dans la section "Mixage des accesseurs synthétisés et personnalisés", elle est flexible et ne génère pas de méthodes si vous les implémentez. ).

211
Alex Rozanski

Comme d'autres l'ont déjà dit, vous utilisez généralement @synthesize pour que le compilateur génère les getters et/ou les paramètres pour vous, et @dynamic si vous allez les écrire vous-même.

Il existe une autre subtilité non encore mentionnée: @synthesize will vous permet de fournir vous-même une implémentation, d'un getter ou d'un setter. Ceci est utile si vous voulez seulement implémenter le getter pour une logique supplémentaire, mais laissez le compilateur générer le setter (qui, pour les objets, est généralement un peu plus complexe à écrire vous-même).

Toutefois, si vous écrivez une implémentation pour un accesseur @ synthesize, celle-ci doit toujours être sauvegardée par un champ réel (par exemple, si vous écrivez -(int) getFoo();, vous devez avoir un champ int foo;). Si la valeur est produite par quelque chose d'autre (par exemple, calculée à partir d'autres champs), vous devez utiliser @dynamic.

29
philsquared

voici exemple de @dynamic

#import <Foundation/Foundation.h>

@interface Book : NSObject
{
   NSMutableDictionary *data;
}
@property (retain) NSString *title;
@property (retain) NSString *author;
@end

@implementation Book
@dynamic title, author;

- (id)init
{
    if ((self = [super init])) {
        data = [[NSMutableDictionary alloc] init];
        [data setObject:@"Tom Sawyer" forKey:@"title"];
        [data setObject:@"Mark Twain" forKey:@"author"];
    }
    return self;
}

- (void)dealloc
{
    [data release];
    [super dealloc];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
    NSString *sel = NSStringFromSelector(selector);
    if ([sel rangeOfString:@"set"].location == 0) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    } else {
        return [NSMethodSignature signatureWithObjCTypes:"@@:"];
    }
 }

- (void)forwardInvocation:(NSInvocation *)invocation
{
    NSString *key = NSStringFromSelector([invocation selector]);
    if ([key rangeOfString:@"set"].location == 0) {
        key = [[key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];
        NSString *obj;
        [invocation getArgument:&obj atIndex:2];
        [data setObject:obj forKey:key];
    } else {
        NSString *obj = [data objectForKey:key];
        [invocation setReturnValue:&obj];
    }
}

@end

int main(int argc, char **argv)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    Book *book = [[Book alloc] init];
    printf("%s is written by %s\n", [book.title UTF8String], [book.author UTF8String]);
    book.title = @"1984";
    book.author = @"George Orwell";
    printf("%s is written by %s\n", [book.title UTF8String], [book.author UTF8String]);

   [book release];
   [pool release];
   return 0;
}
14
mirror

@dynamic est généralement utilisé (comme cela a été dit plus haut) lorsqu'une propriété est créée dynamiquement au moment de l'exécution. NSManagedObject fait cela (pourquoi toutes ses propriétés sont dynamiques) - ce qui supprime certains avertissements du compilateur.

Pour une bonne vue d'ensemble sur la création dynamique de propriétés (sans NSManagedObject et CoreData:), voir: http://developer.Apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Article/ocrtDynamicResolution. html # // Apple_ref/doc/uid/TP40008048-CH102-SW1

14
mifortin

Selon la documentation:

https://developer.Apple.com/library/mac/documentation/cocoa/conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html

@dynamic indique au compilateur que les méthodes d'accès sont fournies au moment de l'exécution.

Après un peu d'investigation, j'ai découvert que la fourniture de méthodes d'accès annule la directive @dynamic.

@synthesize indique au compilateur de créer ces accesseurs pour vous (getter et setter)

@property indique au compilateur que les accesseurs seront créés et accessibles via la notation par points ou par [message d'objet]

10
user1447414

Une chose à ajouter est que si une propriété est déclarée comme @dynamic, elle n'occupera pas de mémoire (j'ai confirmé avec un instrument d'allocation). Une conséquence est que vous pouvez déclarer une propriété dans la catégorie de classe.

6
Yingpei Zeng

Selon la documentation Apple.

Vous utilisez l’instruction @synthesize dans le bloc d’implémentation d’une classe pour indiquer au compilateur de créer des implémentations qui correspondent à la spécification donnée dans la déclaration @property.

Vous utilisez l’instruction @dynamic pour indiquer au compilateur de supprimer un avertissement s’il ne parvient pas à trouver une implémentation des méthodes d’accesseur spécifiées par une déclaration @property.

Plus d'infos: -

https://developer.Apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/DeclaredProperty.html

1
arango_86