@synthesize vs @dynamic, каковы различия?

В чем разница между реализацией @property с @dynamic или @synthesize?

Ответ 1

@synthesize будет генерировать методы getter и setter для вашего свойства. @dynamic просто сообщает компилятору, что методы getter и setter реализуются не самим классом, а где-то в другом месте (например, суперкласс или будут предоставлены во время выполнения).

Использование для @dynamic - это, например, с подклассами NSManagedObject (CoreData) или когда вы хотите создать выход для свойства, определенного суперклассом, который не был определен как выход.

@dynamic также может использоваться для делегирования ответственности за внедрение аксессуаров. Если вы реализуете аксессуры самостоятельно в классе, вы обычно не используете @dynamic.

Суперкласс:

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

Подкласс:

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

Ответ 2

Взгляните на эту статью; под заголовком "Методы, предоставленные во время выполнения":

Некоторые аксессоры создаются динамически во время выполнения, например, некоторые из них используются в классе CoreData NSManagedObject. Если вы хотите объявить и использовать свойства для этих случаев, но хотите избежать предупреждений о методах, отсутствующих во время компиляции, вы можете использовать директиву @dynamic вместо @synthesize.

...

Использование директивы @dynamic по сути говорит компилятору: "Не беспокойтесь об этом, метод находится в пути".

Директива @synthesize, с другой стороны, генерирует методы доступа для вас во время компиляции (хотя, как указано в разделе "Смешивание синтезированных и пользовательских аксессуаров", оно является гибким и не генерирует методы для вас, если они реализована).

Ответ 3

Как говорили другие, в общем случае вы используете @synthesize, чтобы компилятор генерировал геттеры и/или настройки для вас, и @dynamic, если вы собираетесь писать их самостоятельно.

Есть еще одна тонкость, о которой еще не упоминалось: @synthesize позволит вам реализовать реализацию самостоятельно, либо геттера, либо сеттера. Это полезно, если вы хотите только реализовать getter для некоторой дополнительной логики, но пусть компилятор сгенерирует setter (который для объектов обычно немного сложнее писать самостоятельно).

Однако, если вы пишете реализацию для аксессуара @synthesize'd, она все равно должна поддерживаться реальным полем (например, если вы пишете -(int) getFoo();, вы должны иметь поле int foo;). Если значение генерируется чем-то другим (например, рассчитано из других полей), вы должны использовать @dynamic.

Ответ 4

@dynamic обычно используется (как было сказано выше), когда свойство динамически создается во время выполнения. NSManagedObject делает это (почему все его свойства являются динамическими), что подавляет некоторые предупреждения компилятора.

Для получения хорошего обзора о том, как создавать свойства динамически (без NSManagedObject и CoreData: см. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#//apple_ref/doc/uid/TP40008048-CH102-SW1

Ответ 5

здесь пример @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:"[email protected]:@"];
    } 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;
}

Ответ 6

В соответствии с документацией:

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

@dynamic сообщает компилятору, что методы доступа доступны во время выполнения.

С небольшим расследованием я обнаружил, что предоставление методов доступа переопределяет директиву @dynamic.

@synthesize сообщает компилятору создать для вас эти аксессуры (getter и setter)

@property сообщает компилятору, что будут созданы аксессоры, и к ним можно получить доступ с помощью точечной нотации или [сообщения объекта]

Ответ 7

Одна вещь, которую нужно добавить, состоит в том, что если свойство объявлено как @dynamic, оно не будет занимать память (я подтвердил с помощью инструмента распределения). В результате вы можете объявить свойство в классе.

Ответ 8

В соответствии с документацией Apple.

Вы используете оператор @synthesize в блоке реализации классов, чтобы сообщить компилятору создать реализации, которые соответствуют спецификации, указанной в объявлении @property.

Вы используете оператор @dynamic, чтобы сообщить компилятору подавить предупреждение, если он не может найти реализацию методов доступа, указанных в объявлении @property.

Дополнительная информация: -

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