@synthesize vs @dynamic, jakie są różnice?

Odpowiedzi:

744

@synthesize wygeneruje metody pobierające i ustawiające dla Twojej właściwości. @dynamic po prostu mówi kompilatorowi, że metody pobierające i ustawiające są implementowane nie przez samą klasę, ale gdzie indziej (np. nadklasę lub zostaną udostępnione w czasie wykonywania).

Zastosowania @dynamic są np. Z podklasami NSManagedObject(CoreData) lub gdy chcesz utworzyć ujście dla właściwości zdefiniowanej przez nadklasę, która nie została zdefiniowana jako ujście.

@dynamic można również wykorzystać do przekazania odpowiedzialności za implementację akcesoriów. Jeśli implementujesz akcesoria samodzielnie w klasie, zwykle nie używasz @dynamic.

Super klasa:

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

Podklasa:

@property (nonatomic, retain) IBOutlet NSButton *someButton;
...
@dynamic someButton;
Dieterikh
źródło
25
nie w 100% słuszny; dynamiczny jest domyślny, jeśli nie ustawisz @synthesize ani @dynamic. określenie @dynamic oznacza po prostu, że bierzesz odpowiedzialność za prawidłowe wdrożenie akcesorów właściwości na podstawie podpisu deklaracji własności.
Kevlar
68
Nie do końca, @dynamic oznacza, że ​​odpowiedzialność za wdrożenie akcesoriów jest delegowana. Jeśli implementujesz akcesoria samodzielnie w klasie, zwykle nie używasz @dynamic.
dieerikh
2
NSUnknownKeyExceptionPodczas usuwania @synthesizelinii pojawiały się błędy w mojej właściwości dynamicznej (Xcode 3.2 dawał mi błąd b / c, że nie miałem pasującego ivar dla mojej @property). Dodanie @dynamicnaprawiło problem - teraz kompiluje się i działa poprawnie. Dzięki!
pix0r
4
Przepraszamy, kup to jest całkowicie błędne. @dynamic mówi, że akcesory są rozwiązywane w czasie wykonywania, chyba że są zadeklarowane w klasie lub nadklasie (nie gdzie indziej). Możesz przeczytać dokumentację developer.apple.com/library/mac/documentation/cocoa/conceptual/…
user1447414
5
Kevlar: nie. We współczesnym ObjC @propertyprzedmioty, które nie mają ani @synthesizenie @dynamicbędą automatycznie syntezowane. Dla każdej właściwości zostanie utworzony ivar z wiodącym podkreśleniem, np. _propertyNameWraz z odpowiednim narzędziem pobierającym i ustawiającym.
Dave R
212

Spójrz na ten artykuł ; w tytule „Metody udostępniane w czasie wykonywania”:

Niektóre akcesoria są tworzone dynamicznie w czasie wykonywania, takie jak niektóre używane w klasie NSManagedObject CoreData. Jeśli chcesz zadeklarować i użyć właściwości dla tych przypadków, ale chcesz uniknąć ostrzeżeń o metodach brakujących w czasie kompilacji, możesz użyć dyrektywy @dynamic zamiast @synthesize.

...

Użycie dyrektywy @dynamic zasadniczo mówi kompilatorowi: „nie martw się, metoda jest w drodze”.

Z @synthesizedrugiej strony dyrektywa generuje dla ciebie metody akcesora w czasie kompilacji (chociaż, jak zauważono w sekcji „Miksowanie syntetycznych i niestandardowych akcesoriów”, jest elastyczna i nie generuje metod, jeśli którekolwiek są zaimplementowane).

Alex Różański
źródło
27
To jest człowiek bardziej skorygowany. Ta odpowiedź jest jedyną odpowiedzią, która mówi o metodach stworzonych w środowisku uruchomieniowym, które naprawdę naprawdę wychwytują ducha o wiele bardziej niż najwyżej głosowani ans atm
bobobobo
30

Jak powiedzieli inni, zazwyczaj używasz @synthesize, aby kompilator wygenerował dla ciebie gettery i / lub ustawienia, a @dynamic, jeśli masz zamiar je napisać.

Jest jeszcze inny subtelność jeszcze wymienić: @synthesize będzie pozwalają zapewnić implementację siebie, albo z getter i setter. Jest to przydatne, jeśli chcesz zaimplementować moduł pobierający tylko w celu uzyskania dodatkowej logiki, ale pozwól kompilatorowi wygenerować moduł ustawiający (który dla obiektów jest zwykle nieco trudniejszy do napisania).

Jednak jeśli napiszesz implementację dla akcesorium @ syntezowanego, to musi ona być jeszcze poparta prawdziwym polem (np. Jeśli piszesz -(int) getFoo();, musisz mieć int foo;pole). Jeśli wartość jest wytwarzana przez coś innego (np. Obliczana z innych pól), musisz użyć @dynamic.

philsquared
źródło
2
+1 za wzmiankę o ważnej różnicy: @dynamic pozwala tworzyć akcesoria dla zmiennych, które nie są zdefiniowane w interfejsie klasy i poprzez introspekcję.
mahboudz,
24
„a @dynamicjeśli zamierzasz je napisać sam” NIE, nie używasz dynamiki, jeśli sam je piszesz. @dynamicwyłącza sprawdzanie kompilatora, aby upewnić się, że zostały zaimplementowane. Jeśli sam je zaimplementowałeś, chcesz, aby kompilator sprawdził.
user102008
14

@dynamic jest zwykle używany (jak wspomniano powyżej), gdy właściwość jest dynamicznie tworzona w czasie wykonywania. NSManagedObject robi to (dlaczego wszystkie jego właściwości są dynamiczne) - co eliminuje niektóre ostrzeżenia kompilatora.

Dobry przegląd dynamicznego tworzenia właściwości (bez NSManagedObject i CoreData :, patrz: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#// apple_ref / doc / uid / TP40008048-CH102-SW1

mifortin
źródło
14

oto przykład @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;
}
lustro
źródło
10

Zgodnie z dokumentacją:

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

@dynamic informuje kompilator, że metody dostępu są udostępniane w czasie wykonywania.

Po krótkim dochodzeniu dowiedziałem się, że udostępnienie metod akcesorium zastępuje dyrektywę @dynamic.

@synthesize mówi kompilatorowi, aby utworzył dla ciebie te akcesoria (getter i setter)

@property informuje kompilator, że akcesory zostaną utworzone i że można uzyskać do nich dostęp za pomocą notacji kropkowej lub [komunikatu obiektowego]

użytkownik1447414
źródło
6

Jedną rzeczą, którą chcę dodać, jest to, że jeśli właściwość zostanie zadeklarowana jako @dynamic, nie zajmie ona pamięci (potwierdziłem za pomocą instrumentu alokacji). Konsekwencją jest to, że możesz zadeklarować właściwość w kategorii klasy.

Yingpei Zeng
źródło
Jeśli przesłonię ustawiacz właściwości w kategorii i ustawię go jako dynamiczny, czy to zagwarantuje, że zastąpienie zostanie użyte w czasie wykonywania, a nie ustawiacz klasy nadrzędnej? Z dokumentów Apple: „Jeśli nazwa metody zadeklarowanej w kategorii jest taka sama jak metoda w klasie oryginalnej ... zachowanie nie jest określone, która implementacja metody jest używana w czasie wykonywania”.
David James
Nie, myślę, że zachowanie jest nadal niezdefiniowane. Ustawienie właściwości w kategorii dynamicznej nie zmienia priorytetu czasu wykonywania metody ustawiacza właściwości.
Yingpei Zeng,
3

Zgodnie z dokumentacją Apple.

Używasz @synthesizeinstrukcji w bloku implementacyjnym klasy, aby powiedzieć kompilatorowi, aby utworzył implementacje pasujące do specyfikacji podanej w @propertydeklaracji.

@dynamicInstrukcja służy do informowania kompilatora, aby pomijał ostrzeżenie, jeśli nie może znaleźć implementacji metod dostępu określonych w @propertydeklaracji.

Więcej informacji:-

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

arango_86
źródło