@synthesize बनाम @dynamic, क्या अंतर हैं?


जवाबों:


744

@synthesize आपकी संपत्ति के लिए गेट्टर और सेटर विधियां उत्पन्न करेगा। @dynamic सिर्फ कंपाइलर को बताता है कि गेटर और सेटर के तरीके क्लास द्वारा ही नहीं बल्कि कहीं और लागू किए जाते हैं (जैसे सुपरक्लास या रनटाइम के दौरान दिए जाएंगे)।

@Dynamic के लिए उपयोग उदाहरण के लिए NSManagedObject(CoreData) के उपवर्गों के साथ या जब आप एक सुपरक्लास द्वारा परिभाषित संपत्ति के लिए एक आउटलेट बनाना चाहते हैं जिसे आउटलेट के रूप में परिभाषित नहीं किया गया था।

@ डायनामिक का उपयोग एक्सेसर्स को लागू करने की जिम्मेदारी सौंपने के लिए भी किया जा सकता है। यदि आप एक्सेसर्स को स्वयं कक्षा के भीतर लागू करते हैं तो आप आमतौर पर @dynamic का उपयोग नहीं करते हैं।

सुपर क्लास:

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

उपवर्ग:

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

25
100% सही नहीं है; यदि आप @synthesize या @dynamic सेट नहीं करते हैं तो डायनेमिक डिफ़ॉल्ट है। @dynamic को निर्दिष्ट करने का अर्थ केवल यह है कि आप संपत्ति की घोषणा के हस्ताक्षर के आधार पर संपत्ति एक्सेसरों को ठीक से लागू करने की जिम्मेदारी लेते हैं।
केवलर

68
वास्तव में, @dynamic का मतलब एक्सेसर्स को लागू करने की जिम्मेदारी नहीं है। यदि आप एक्सेसर्स को स्वयं कक्षा के भीतर लागू करते हैं तो आप आमतौर पर @dynamic का उपयोग नहीं करते हैं।
डेडेरिख

2
मुझे NSUnknownKeyExceptionअपनी डायनेमिक प्रॉपर्टी में त्रुटियां हो रही थीं जब मैंने @synthesizeलाइन को हटा दिया था (Xcode 3.2 मुझे एक त्रुटि दे रहा था b / c मेरे पास मेरे @property के लिए कोई मिलान ivar नहीं था)। @dynamicफिक्स्ड मुद्दे को जोड़ना - संकलन और अब ठीक चलता है। धन्यवाद!
पिक्स्र्र

4
क्षमा करें, इसे खरीदना पूरी तरह से गलत है। @dynamic बताता है कि एक्सेसर्स को रनटाइम पर हल किया जाता है, जब तक कि उन्हें क्लास या सुपरक्लास में घोषित नहीं किया जाता है (कहीं और नहीं)। आप प्रलेखन डेवलपर
।apple.com

5
केवलर: नहीं। आधुनिक ObjC में, ऐसे @propertyआइटम जिनके पास न तो ऑटो-सिंथेसाइज्ड होगा @synthesizeऔर न ही @dynamicहोगा। प्रत्येक संपत्ति के लिए, एक प्रमुख अंडरस्कोर के साथ एक आइवर, जैसे _propertyNameउचित गेट्टर और सेटर के साथ बनाया जाएगा।
डेव आर

212

इस लेख पर एक नज़र डालें ; "रनटाइम पर प्रदान की जाने वाली विधियाँ" शीर्षक के तहत:

कुछ एक्सेसरों को गतिशील रूप से रनटाइम पर बनाया जाता है, जैसे कि कोरडाटा के NSManagedObject क्लास में उपयोग किए जाने वाले कुछ। यदि आप इन मामलों के लिए संपत्तियों की घोषणा करना और उनका उपयोग करना चाहते हैं, लेकिन संकलन समय पर गायब होने वाले तरीकों के बारे में चेतावनी से बचना चाहते हैं, तो आप @synthesize के बजाय @dynamic निर्देश का उपयोग कर सकते हैं।

...

@Dynamic निर्देश का उपयोग अनिवार्य रूप से संकलक को बताता है "इसके बारे में चिंता न करें, एक तरीका रास्ते में है।"

@synthesizeनिर्देश, दूसरे हाथ पर, संकलन समय पर आप के लिए एक्सेसर तरीकों उत्पन्न करता है (हालांकि के रूप में "मिश्रण संश्लेषित और कस्टम पहुंचकर्ता" खंड में बताया गया है कि यह लचीला है और यदि या तो लागू किया जाता है आप के लिए तरीकों उत्पन्न नहीं करता है)।


27
यह प्रफुल्लित करने वाला है। यह उत्तर एकमात्र ऐसा उत्तर है जो रनटाइम के दौरान बनाए गए तरीकों के बारे में बात करता है, जो वास्तव में भावना को बहुत ज्यादा वोट देने वाले
एएनएम

30

जैसा कि दूसरों ने कहा है, सामान्य तौर पर आप @synthesize का उपयोग करने के लिए कंपाइलर आपके लिए गेटर और / या सेटिंग्स उत्पन्न करते हैं, और @dynamic यदि आप उन्हें स्वयं लिखने जा रहे हैं।

एक और सूक्ष्मता है जिसका अभी तक उल्लेख नहीं किया गया है: @ साइनइनसाइज़ आपको एक या तो एक सेटर या सेटर के रूप में खुद को एक कार्यान्वयन प्रदान करेगा । यह उपयोगी है यदि आप केवल कुछ अतिरिक्त तर्क के लिए गटर को लागू करना चाहते हैं, लेकिन कंपाइलर सेटर उत्पन्न करते हैं (जो, वस्तुओं के लिए, आमतौर पर अपने आप को लिखने के लिए थोड़ा अधिक जटिल होता है)।

हालाँकि, अगर आप @ सिंथेसाइज्ड एक्सेसर के लिए इम्प्लीमेंटेशन लिखते हैं, तो इसे अभी भी एक वास्तविक फ़ील्ड (जैसे, यदि आप लिखते -(int) getFoo();हैं कि आपके पास int foo;फ़ील्ड होना चाहिए ) द्वारा समर्थित होना चाहिए । यदि मूल्य कुछ और द्वारा उत्पादित किया जा रहा है (जैसे अन्य क्षेत्रों से गणना) तो आपको @dynamic का उपयोग करना होगा।


2
+1 महत्वपूर्ण अंतर के उल्लेख के लिए: @dynamic आपको वैरिएबल के लिए एक्सेसर्स बनाने देता है जो आपके क्लास इंटरफ़ेस में और आत्मनिरीक्षण के माध्यम से परिभाषित नहीं है।
महबूदज़

24
"और @dynamicयदि आप उन्हें स्वयं लिखने जा रहे हैं" नहीं, यदि आप स्वयं लिखते हैं तो आप गतिशील का उपयोग नहीं करते हैं। @dynamicयह सुनिश्चित करने के लिए संकलक जाँच बंद कर देता है कि आपने उन्हें कार्यान्वित किया है। यदि आपने उन्हें स्वयं कार्यान्वित किया है, तो आप चाहते हैं कि संकलक जाँच करे।
उपयोगकर्ता 102008

14

@dynamic का उपयोग आम तौर पर किया जाता है (जैसा कि ऊपर कहा गया है) जब किसी संपत्ति को गतिशील रूप से रनटाइम पर बनाया जाता है। NSManagedObject ऐसा करता है (इसके सभी गुण गतिशील क्यों हैं) - जो कुछ संकलक चेतावनियों को दबा देता है।

गतिशील रूप से गुण बनाने के तरीके पर एक अच्छे अवलोकन के लिए (बिना NSManagedObject और CoreData के बिना :, देखें: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObcCRuntimeGuide/Articles/ocrtDynamicResolution.html#// apple_ref / doc / यूआईडी / TP40008048-CH102-SW1


14

यहाँ @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;
}

10

प्रलेखन के अनुसार:

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

@dynamic कंपाइलर को बताता है कि रनटाइम पर एक्सेसर के तरीके उपलब्ध कराए जाते हैं।

थोड़ी सी जाँच के साथ मुझे पता चला कि एक्सेसरी मेथड उपलब्ध कराने के लिए @ डायनामिक निर्देश को ओवरराइड किया गया है।

@ synthesize कंपाइलर को आपके लिए वे एक्सेसर्स बनाने के लिए कहता है (गेट्टर और सेटर)

@property कंपाइलर को बताता है कि एक्सेसर्स बनाए जाएंगे, और इसे डॉट नोटेशन या [ऑब्जेक्ट मैसेज] के साथ एक्सेस किया जा सकता है


6

एक बात यह जोड़ना चाहते हैं कि अगर किसी संपत्ति को @dynamic घोषित किया जाता है तो वह मेमोरी पर कब्जा नहीं करेगी (मैंने आवंटन साधन के साथ पुष्टि की है)। एक परिणाम यह है कि आप वर्ग श्रेणी में संपत्ति की घोषणा कर सकते हैं।


यदि मैं किसी श्रेणी में एक संपत्ति सेटर को ओवरराइड करता हूं और इसे गतिशील बनाता हूं, तो क्या यह गारंटी ओवरराइड का उपयोग रनटाइम पर किया जाएगा और अभिभावक वर्ग के सेटर में नहीं? Apple डॉक्स से: "यदि किसी श्रेणी में घोषित विधि का नाम मूल वर्ग में एक विधि के समान है ... तो व्यवहार अपरिभाषित है कि किस विधि का उपयोग रनटाइम में किया जाता है।"
डेविड जेम्स

नहीं, मुझे लगता है कि व्यवहार अभी भी अपरिभाषित है। प्रॉपर्टी को कैटेगरी डायनेमिक बनाने से प्रॉपर्टी सेटर मेथड की रनटाइम प्राथमिकता में बदलाव नहीं होता है।
यिंगपी ज़ेंग

3

Apple प्रलेखन के अनुसार।

आप घोषणा @synthesizeमें दिए गए विनिर्देश से मेल खाने वाले कार्यान्वयन को बनाने के लिए संकलक को बताने के लिए एक वर्ग के कार्यान्वयन ब्लॉक में बयान का उपयोग करते हैं @property

यदि आप @dynamicएक @propertyघोषणा द्वारा निर्दिष्ट एक्सेसर विधियों के कार्यान्वयन को नहीं ढूँढ सकते हैं तो आप एक चेतावनी को दबाने के लिए संकलक को बताने के लिए कथन का उपयोग करते हैं ।

और जानकारी:-

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.