570

What are the differences between implementing a @property with @dynamic or @synthesize?

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
nico
  • 9,668
  • 8
  • 26
  • 28

8 Answers8

751

@synthesize will generate getter and setter methods for your property. @dynamic just tells the compiler that the getter and setter methods are implemented not by the class itself but somewhere else (like the superclass or will be provided at runtime).

Uses for @dynamic are e.g. with subclasses of NSManagedObject (CoreData) or when you want to create an outlet for a property defined by a superclass that was not defined as an outlet.

@dynamic also can be used to delegate the responsibility of implementing the accessors. If you implement the accessors yourself within the class then you normally do not use @dynamic.

Super class:

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

Subclass:

@property (nonatomic, retain) IBOutlet NSButton *someButton;
...
@dynamic someButton;
iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
diederikh
  • 25,221
  • 5
  • 36
  • 49
  • 26
    not 100% right; dynamic is the default if you don't set either @synthesize or @dynamic. specifying @dynamic merely means that you take responsibility for properly implementing the property accessors based on the signature of the property declaration. – Kevlar Jul 22 '09 at 05:52
  • 70
    Not really, @dynamic means to responsibility of implementing the accessors is delegated. If you implement the accessors yourself within the class then you normally do not use @dynamic. – diederikh Jul 22 '09 at 12:37
  • 2
    I was getting `NSUnknownKeyException` errors with my dynamic property when I removed the `@synthesize` line (Xcode 3.2 was giving me an error b/c I had no matching ivar for my @property). Adding `@dynamic` fixed the issue - compiles and runs fine now. Thanks! – pix0r Sep 14 '09 at 17:59
  • 1
    @DiederikHoogenboom: I did not understand one thing, If the parent class or some other class up in the hierarchy defines the setters and getters then, child class will already have them. Then why would a child class again define property and tell the compiler that the definition of setter or getter is in the parent class ? I did not understand the importance here. Can you explain me this in terms of NSManagedObject Subclasses ? or point me to a link that explains this clearly :) – Amogh Talpallikar Jan 22 '13 at 10:00
  • 1
    @Amogh: NSManagedObject does not have the property but does have the getters and setters (it uses KVC to resolve to attributes). Another usage is a parent class that has the (abstract) property but expects subclasses to implement the getters and setters. – diederikh Jan 22 '13 at 19:21
  • by saying "Another usage is a parent class that has the (abstract) property but expects subclasses to implement the getters and setters". By saying this, do you mean that, parent abstract class will have dynamic in its implementation ? that means dynamic just says the the setters and getters are like abstract functions(java terms) or virtual functions (C++) and binding will dynamic ? and regarding NSManagedObject, what I understand from your statement is that, a core data generatd class reads and writes data frm SQLite store and the datamodel. So it happens at runtime via KVC. AM I right? – Amogh Talpallikar Jan 23 '13 at 04:47
  • 1
    @Amogh:Yes, that's more or less the idea. The Core Data generated class does not read from the SQLite store, it's the NSPersistentStore object. But is is done at runtime. – diederikh Jan 24 '13 at 09:05
  • 4
    Sorry, buy this is entirely wrong. @dynamic tells that the accessors are resolved at runtime, unless they are declared in the class or superclass (not somewhere else). You can read the documentation https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html – user1447414 Dec 03 '13 at 18:21
  • 5
    Kevlar: nope. In modern ObjC, `@property` items that have neither `@synthesize` nor `@dynamic` will be auto-synthesized. For each property, an ivar with a leading underscore, e.g. `_propertyName` will be created, along with the appropriate getter and setter. – Dave R Jan 26 '14 at 19:54
  • @iWasRobbed: Why did you add the paragraph "@dynamic also can be used to delegate the responsibility of....". Isn't that what the first paragraph says? – diederikh Jul 11 '16 at 15:29
214

Take a look at this article; under the heading "Methods provided at runtime":

Some accessors are created dynamically at runtime, such as certain ones used in CoreData's NSManagedObject class. If you want to declare and use properties for these cases, but want to avoid warnings about methods missing at compile time, you can use the @dynamic directive instead of @synthesize.

...

Using the @dynamic directive essentially tells the compiler "don't worry about it, a method is on the way."

The @synthesize directive, on the other hand, generates the accessor methods for you at compile time (although as noted in the "Mixing Synthesized and Custom Accessors" section it is flexible and does not generate methods for you if either are implemented).

Alex Rozanski
  • 37,815
  • 10
  • 68
  • 69
  • 27
    This is morer-correcter man. This answer is the only answer that talks about methods created at runtime, which really seems to capture the spirit a lot more than top voted ans atm – bobobobo Nov 25 '09 at 05:11
32

As others have said, in general you use @synthesize to have the compiler generate the getters and/ or settings for you, and @dynamic if you are going to write them yourself.

There is another subtlety not yet mentioned: @synthesize will let you provide an implementation yourself, of either a getter or a setter. This is useful if you only want to implement the getter for some extra logic, but let the compiler generate the setter (which, for objects, is usually a bit more complex to write yourself).

However, if you do write an implementation for a @synthesize'd accessor it must still be backed by a real field (e.g., if you write -(int) getFoo(); you must have an int foo; field). If the value is being produce by something else (e.g. calculated from other fields) then you have to use @dynamic.

philsquared
  • 22,403
  • 12
  • 69
  • 98
  • 2
    +1 for mention of important difference: @dynamic lets you create accessors for varaibles not defined in your class interface and through introspection. – mahboudz Nov 20 '09 at 00:02
  • 25
    "and `@dynamic` if you are going to write them yourself" No, you do NOT use dynamic if you write them yourself. `@dynamic` turns off the compiler checking to make sure you implemented them. If you implemented them yourself, you do want the compiler to check. – user102008 Jul 20 '11 at 23:01
14

here is example of @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;
}
mirror
  • 345
  • 3
  • 10
14

@dynamic is typically used (as has been said above) when a property is being dynamically created at runtime. NSManagedObject does this (why all its properties are dynamic) -- which suppresses some compiler warnings.

For a good overview on how to create properties dynamically (without NSManagedObject and CoreData:, see: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#//apple_ref/doc/uid/TP40008048-CH102-SW1

mifortin
  • 401
  • 4
  • 4
11

As per the documentation:

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

@dynamic tells the compiler that the accessor methods are provided at runtime.

With a little bit of investigation I found out that providing accessor methods override the @dynamic directive.

@synthesize tells the compiler to create those accessors for you (getter and setter)

@property tells the compiler that the accessors will be created, and that can be accessed with the dot notation or [object message]

user1447414
  • 1,306
  • 2
  • 12
  • 25
6

One thing want to add is that if a property is declared as @dynamic it will not occupy memory (I confirmed with allocation instrument). A consequence is that you can declare property in class category.

Yingpei Zeng
  • 515
  • 8
  • 10
  • If I override a property setter in a category and make it dynamic, will this guarantee the override will be used at runtime and not the parent class's setter? From Apple docs: "If the name of a method declared in a category is the same as a method in the original class ... the behavior is undefined as to which method implementation is used at runtime." – David James Apr 06 '15 at 12:58
  • No, I think the behavior is still undefined. Making the property in category dynamic doesn't change the property setter method's runtime priority. – Yingpei Zeng Apr 07 '15 at 02:51
4

As per the Apple documentation.

You use the @synthesize statement in a class’s implementation block to tell the compiler to create implementations that match the specification you gave in the @property declaration.

You use the @dynamic statement to tell the compiler to suppress a warning if it can’t find an implementation of accessor methods specified by an @property declaration.

More info:-

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

arango_86
  • 4,236
  • 4
  • 40
  • 46