@synthesize vs @dynamic, farkları nelerdir?


Yanıtlar:


744

@synthesize, mülkünüz için alıcı ve ayarlayıcı yöntemleri oluşturur. @dinamik derleyiciye getter ve setter yöntemlerinin sınıfın kendisi tarafından değil başka bir yerde (üst sınıf gibi veya çalışma zamanında sağlanacağını) uygulandığını söyler.

@Dinamik için kullanımlar, örneğin NSManagedObject(CoreData) alt sınıflarıyla veya çıkış olarak tanımlanmayan bir üst sınıf tarafından tanımlanan bir özellik için bir çıkış oluşturmak istediğinizde kullanılır.

@dinamik ayrıca erişimcileri uygulama sorumluluğunu devretmek için de kullanılabilir. Erişimcileri sınıf içinde kendiniz uygularsanız, normalde @dinamik kullanmazsınız.

Süper sınıf:

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

Alt sınıf:

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

25
% 100 doğru değil; @synthesize veya @dinamik ayarlamazsanız, dinamik varsayılan değerdir. @dinamik belirtmek, mülk bildiricisinin imzasına dayalı olarak mülk erişimcilerini düzgün bir şekilde uygulama sorumluluğunu almanız anlamına gelir.
Kevlar

68
Pek değil, @dinamik erişimcilerin uygulanmasının sorumluluğu anlamına gelir. Erişimcileri sınıf içinde kendiniz uygularsanız, normalde @dinamik kullanmazsınız.
loseerikh

2
Satırı NSUnknownKeyExceptionkaldırdığımda dinamik özelliğimle ilgili hatalar alıyordum @synthesize(Xcode 3.2 bana bir hata verdi b / c @ @property için eşleşen ivar yoktu). Ekleme @dynamicsorunu düzeltti - derler ve şimdi iyi çalışıyor. Teşekkürler!
pix0r

4
Üzgünüm, satın almak bu tamamen yanlış. @dinamik, sınıfta veya üst sınıfta (başka bir yerde değil) bildirilmedikçe erişimcilerin çalışma zamanında çözümlendiğini söyler. Belgelerinizi geliştirici
user1447414

5
Kevlar: hayır. Modern ObjC'de @propertyne otomatik olarak sentezlenecek ne @synthesizede @dynamicsentezlenecek öğeler . Her bir mülk için, _propertyNameuygun alıcı ve ayarlayıcı ile birlikte , örneğin alt çizgi içeren bir ivar oluşturulacaktır.
Dave R

212

Bu makaleye bir göz atın ; "Çalışma zamanında sağlanan yöntemler" başlığı altında:

CoreData'nın NSManagedObject sınıfında kullanılanlar gibi bazı erişimciler çalışma zamanında dinamik olarak oluşturulur. Bu durumlar için özellikler bildirmek ve kullanmak istiyorsanız, ancak derleme zamanında eksik olan yöntemlerle ilgili uyarıları önlemek istiyorsanız, @synthesize yerine @dinamik yönergesini kullanabilirsiniz.

...

@Dinamik yönergesini kullanarak derleyiciye "endişelenmeyin, bir yöntem geliyor" der.

@synthesize( "Karıştırma Sentezlenen ve Özel Erişimciler" bölümünde belirtildiği gibi esnektir ve ya uygulanması halinde sizin için yöntemler oluşturmaz rağmen) direktifi, diğer taraftan, derleme sırasında sizin için bir erişim yöntemine üretir.


27
Bu daha düzeltici bir adam. Bu cevap, çalışma zamanında yaratılan yöntemler hakkında konuşan tek cevaptır, bu da ruhu gerçekten en çok oy alan ans
atm'den

30

Diğerlerinin söylediği gibi, genel olarak derleyicinin sizin için alıcıları ve / veya ayarları oluşturmasını sağlamak için @synthesize ve bunları kendiniz yazacaksanız @dinamik kullanırsınız.

Henüz bahsedilmeyen başka bir incelik daha var: @synthesize , bir alıcı veya ayarlayıcıdan kendiniz bir uygulama sağlamanıza izin verecektir . Bu, yalnızca bazı ekstra mantık için alıcıyı uygulamak istiyorsanız, ancak derleyicinin ayarlayıcıyı oluşturmasına izin verirseniz (nesneler için genellikle kendinizi yazmak için biraz daha karmaşıksa) kullanışlıdır.

Ancak, @ sentezlenen bir erişimci için bir uygulama yazarsanız, yine de gerçek bir alan tarafından desteklenmelidir (örneğin, yazarsanız bir -(int) getFoo();alanınız olmalıdır int foo;). Değer başka bir şey tarafından üretiliyorsa (örneğin, diğer alanlardan hesaplanırsa), @dinamik kullanmanız gerekir.


2
Önemli farktan bahsetmek için +1: @dinamik, sınıf arayüzünüzde tanımlı olmayan ve introspection yoluyla değişkenler için erişim oluşturmanıza olanak tanır.
mahboudz

24
"ve @dynamicbunları kendiniz yazacaksanız" Hayır, kendiniz yazarsanız dinamik kullanmazsınız. @dynamicuyguladığınızdan emin olmak için derleyici denetimini kapatır. Bunları kendiniz uyguladıysanız, derleyicinin kontrol etmesini istersiniz.
user102008

14

@ dinamik, çalışma zamanında dinamik olarak bir özellik yaratıldığında (yukarıda belirtildiği gibi) genellikle kullanılır. NSManagedObject bunu yapar (tüm özellikleri neden dinamiktir) - bazı derleyici uyarılarını bastırır.

Özelliklerin dinamik olarak nasıl oluşturulacağına (NSManagedObject ve CoreData olmadan) iyi bir genel bakış için bkz: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#// apple_ref / doc / uid / TP40008048-CH102-SW1


14

İşte @dinamik örneği

#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;
}

10

Belgelere göre:

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

@dinamik derleyiciye erişimci yöntemlerinin çalışma zamanında sağlandığını söyler.

Biraz araştırma yaparak, erişimci yöntemleri sağlamanın @dinamik direktifini geçersiz kıldığını öğrendim.

@synthesize derleyiciye sizin için bu erişimcileri oluşturmasını söyler (alıcı ve ayarlayıcı)

@property derleyiciye erişimcilerin oluşturulacağını ve bu noktaya nokta gösterimi veya [nesne mesajı] ile erişilebileceğini söyler


6

Eklemek istediğimiz bir şey, bir özellik @dinamik olarak bildirilirse belleği işgal etmeyeceğidir (ayırma aracıyla onayladım). Bunun bir sonucu olarak, sınıf kategorisinde özellik bildirebilirsiniz.


Bir kategorideki bir özellik ayarlayıcısını geçersiz kılar ve dinamik hale getirirsem, bu geçersiz kılma, üst sınıf ayarlayıcısının değil çalışma zamanında kullanılacağını garanti eder mi? Apple belgelerinden: "Bir kategoride bildirilen bir yöntemin adı orijinal sınıftaki bir yöntemle aynıysa ... davranış, çalışma zamanında hangi yöntem uygulamasının kullanıldığına göre tanımlanmamıştır."
David James

Hayır, bence davranış hala tanımsız. Özelliği kategoride dinamik yapmak, özellik ayarlayıcı yönteminin çalışma zamanı önceliğini değiştirmez.
Yingpei Zeng

3

Apple belgelerine göre.

Sen kullanmak @synthesizesize verdi spesifikasyonu ile uyumlu uygulamaları oluşturmak için derleyici anlatmak için bir sınıfın uygulama bloğunda açıklama@property bildiriminde.

@dynamicDeyimi, derleyiciye bir @propertybildirimle belirtilen erişimci yöntemlerinin bir uygulamasını bulamazsa bir uyarıyı bastırmasını bildirmek için kullanırsınız .

Daha fazla bilgi:-

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.