@synthesize와 @dynamic의 차이점은 무엇입니까?


답변:


744

@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;

25
100 %가 아닙니다. @synthesize 또는 @dynamic을 설정하지 않으면 dynamic이 기본값입니다. @dynamic을 지정하면 속성 선언의 서명을 기반으로 속성 접근자를 올바르게 구현해야 할 책임이 있습니다.
Kevlar

68
실제로, @dynamic은 접근자를 구현하는 책임을 위임한다는 의미입니다. 클래스 내에서 접근자를 직접 구현하면 일반적으로 @dynamic을 사용하지 않습니다.
diederikh

2
줄을 NSUnknownKeyException제거 할 때 동적 속성에 오류 가 발생했습니다 @synthesize(Xcode 3.2에서 @property와 일치하는 ivar가없는 오류 b / c가 발생했습니다). 추가 @dynamic문제 해결-지금 컴파일하고 잘 실행하십시오. 감사!
pix0r

4
죄송합니다. 구매가 완전히 잘못되었습니다. @dynamic은 접근자가 클래스 나 수퍼 클래스 (어딘가에 선언되지 않은)에서 선언되지 않는 한 런타임에 해결된다는 것을 알려줍니다. 문서 developer.apple.com/library/mac/documentation/cocoa/conceptual/…을
user1447414

5
케블라 : 아뇨. 현대 ObjC에서 자동 합성 @property되지 않은 품목도 @synthesize없습니다 @dynamic. 각 속성에 대해 _propertyName적절한 getter 및 setter와 함께 밑줄이있는 ivar 이 만들어집니다.
Dave R

212

한 번 봐 가지고 이 글을 ; "런타임에 제공되는 방법"제목 아래 :

CoreData의 NSManagedObject 클래스에서 사용되는 특정 접근 자와 같은 일부 접근자는 런타임에 동적으로 생성됩니다. 이러한 경우에 속성을 선언하고 사용하려고하지만 컴파일시 누락 된 메서드에 대한 경고를 피하려면 @synthesize 대신 @dynamic 지시문을 사용할 수 있습니다.

...

@dynamic 지시문을 사용하면 본질적으로 컴파일러에게 "걱정하지 말고 방법이 진행 중"이라고 지시합니다.

@synthesize(이하 "혼합 합성하여 사용자 접근 자"절에서 언급 한 바와 같이이 유연하고 중 하나를하는 것은 구현하는 경우 당신을위한 방법을 생성하지 않지만) 지침은, 다른 한편으로는, 컴파일시에 당신을위한 접근 방법을 생성합니다.


27
이 사람은 더 정확한 사람입니다. 이 답변은 유일한 해답입니다 정말 많은 최고 ANS 기압 투표보다 정신을 캡처하는 것 같다 런타임에 생성 방법에 대해 이야기
bobobobo

30

다른 사람들이 말했듯이 일반적으로 @synthesize를 사용하여 컴파일러가 getter 및 / 또는 설정을 생성하게하고 @dynamic을 사용하여 직접 작성하십시오.

아직 언급되지 않은 또 다른 미묘한 점이 있습니다. @synthesize 를 사용하면 getter 또는 setter의 구현을 직접 제공 수 있습니다. 이것은 약간의 추가 로직을 위해 getter를 구현하고 싶지만 컴파일러가 setter를 생성하게하는 경우에 유용합니다.

그러나 @ synthesize'd 접근 자에 대한 구현을 작성하는 경우 여전히 실제 필드에 의해 백업되어야합니다 (예를 들어 작성 -(int) getFoo();하는 경우 int foo;필드 가 있어야 함 ). 다른 필드에서 계산 된 다른 값으로 값을 생성하는 경우 @dynamic을 사용해야합니다.


2
중요한 차이점을 언급하면 ​​+1 : @dynamic을 사용하면 클래스 인터페이스에 정의되지 않았고 내부 검사를 통해 변수에 대한 접근자를 만들 수 있습니다.
mahboudz 2009

24
" @dynamic자신이 직접 작성하려는 경우"아니요, 직접 작성하면 동적을 사용하지 않습니다. @dynamic컴파일러 검사를 해제하여 구현했는지 확인하십시오. 직접 구현 한 경우 컴파일러에서 확인하기를 원합니다.
user102008

14

@dynamic은 속성이 런타임에 동적으로 생성 될 때 일반적으로 사용됩니다 (위에서 언급했듯이). NSManagedObject가이를 수행합니다 (모든 속성이 동적 인 이유). 일부 컴파일러 경고가 표시되지 않습니다.

NSManagedObject 및 CoreData없이 속성을 동적으로 생성하는 방법에 대한 개요는 http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html#//을 참조하십시오. apple_ref / doc / uid / 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은 접근 자 메서드가 런타임에 제공된다는 것을 컴파일러에 알려줍니다.

약간의 조사를 통해 접근 자 메소드를 제공하는 것이 @dynamic 지시문을 재정의한다는 것을 알았습니다.

@synthesize는 컴파일러에게 접근자를 생성하도록 지시합니다 (getter and setter)

@property는 컴파일러에게 접근자가 생성되고 점 표기법 또는 [개체 메시지]로 액세스 할 수 있음을 알려줍니다.


6

추가 할 한 가지 속성은 속성이 @dynamic으로 선언되면 메모리를 차지하지 않는다는 것입니다 (할당 장치로 확인했습니다). 결과적으로 클래스 범주에서 속성을 선언 할 수 있습니다.


범주에서 속성 설정자를 재정의하고 동적으로 만들면 부모 클래스의 설정자가 아닌 런타임에 재정의가 사용되도록 보장합니까? Apple 문서에서 : "카테고리에서 선언 된 메소드의 이름이 원래 클래스의 메소드와 동일한 경우 ... 런타임에 어떤 메소드 구현이 사용되는지에 대해서는 동작이 정의되지 않습니다."
David James

아니요, 행동은 아직 정의되지 않은 것 같습니다. 카테고리의 특성을 동적으로 설정해도 특성 설정 기 메소드의 런타임 우선 순위는 변경되지 않습니다.
Yingpei Zeng

3

Apple 설명서에 따라.

@synthesize클래스의 구현 블록에서 명령문을 사용하여 컴파일러가 사용자가 지정한 사양과 일치하는 구현을 작성하도록 지시합니다.@property .

@dynamic명령문을 사용하여 @property선언에 지정된 접근 자 메소드의 구현을 찾을 수없는 경우 경고를 억제하도록 컴파일러에 지시합니다 .

더 많은 정보:-

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.