집 >백엔드 개발 >C#.Net 튜토리얼 >Objective-C의 @dynamic
1. @dynamic과 @synthesize의 차이점
@property에는 해당 단어가 두 개 있는데, 하나는 @synthesize이고 다른 하나는 @dynamic입니다. @synthesize와 @dynamic 둘 다 작성되지 않은 경우 기본값은 @syntheszie입니다. var = _var;
@synthesize의 의미는 setter 메서드와 getter 메서드를 수동으로 구현하지 않는 경우입니다. 을 누른 다음 컴파일하면 컴파일러가 자동으로 이 두 가지 메서드를 추가합니다.
@dynamic은 속성의 setter 및 getter 메서드가 사용자가 직접 구현하며 자동으로 생성되지 않음을 컴파일러에 알립니다. (물론 읽기 전용 속성의 경우 getter만 제공하면 됩니다.) 속성을 @dynamic var로 선언하고 @setter 메서드와 @getter 메서드를 제공하지 않으면 컴파일 시에는 문제가 없으나, 프로그램이 instance.var = someVar로 실행되면 프로그램이 충돌하게 됩니다. setter 메소드가 부족하거나 someVar = var로 실행할 때 getter 메소드가 없으면 충돌이 발생합니다. 컴파일 타임에는 문제가 없으며 해당 메소드는 런타임에만 실행되는 것을 동적 바인딩이라고 합니다.
2. 개인 변수를 통해 @dynamic 액세스 방법 구현
1) Book.h
#import
__strong NSString *_name; __strong NSString *_author;} @property(비원자, 사본) NSString * 이름;@property(비원자, 복사) NSString *author;@property(비원자, 복사) NSString*version; @end
2) Book.m#import "Book.h" @implementation Book @dynamic name;@dynamicauthor;@synthesizeversion = _version; - (id)init{ self = [super init]; if(self) { } return self ;} - (NSString *)name{ if(nil == _name) { _name = @"입력장 이름을 잊어버렸습니다."; } return _name;} - (void)setName:(NSString *)name{ _name = 이름; NSLog(@"_name 주소:%p", _name );} - (NSString *)author{ if(nil == _author)
{ _author = @"입력북 작성자를 잊어버렸습니다."; } return _author;} - (void)setAuthor:(NSString *)author{ _author = 작성자;} @ end 위 코드에서 볼 수 있듯이 @dynamic을 사용한 후 접근 방식에서 private 변수에 접근하여 값을 할당하거나 얻을 수 있다. 그리고 @synthesize는 @synthesize var = _var;을 직접 사용하여 속성과 개인 변수를 직접 동일시합니다. 이것이 둘 사이의 글쓰기 형식의 차이입니다. 3. 메시지 전달을 통해 @dynamic 액세스 방법 구현 속성에 @dynamic var = _var을 사용하면 컴파일러에서 즉시 오류를 보고합니다. 이런 식으로 @synthesize와 같은 var의 setter 메소드와 getter 메소드에서는 _var를 사용할 수 없습니다. 물론 다음과 같은 setter 메소드와 getter 메소드 - (void)setVar:(id)newVar를 작성할 수는 없습니다. { self.var =newVar;} - (void)var{ return self.var;}이 두 메서드는 자신을 호출하므로 무한 루프가 발생하고 직접적으로 프로그램이 중단됩니다. 다음은 메시지 전달 메커니즘을 사용하여 @dynamic setter 및 getter 메서드를 구현하는 방법입니다. 첫 번째 코드: 1) Book.h#import
_propertiesdict = [[nsMutabledictionary alloc] init];
}
return self; }
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector{ NSString *sel = NSStringFromSelector(selector); if ([sel rangeOfString:@"set"].location == 0) { return [NSMethodSignature signatureWithObjCTypes:"v@:@"]; } else { 반환 [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:&objatIndex:2]; [_propertiesDict setObject:obj forKey:key]; } else { NSString *obj = [_propertiesDict objectForKey:key]; [invocation setReturnValue:&obj]; }} @end 3)main.m#import여기서 v@:@란 무엇인가요? 실제로 여기서 첫 번째 문자 v는 함수의 반환 유형이 void임을 나타냅니다. 다음 세 문자는 위 2)의 설명을 참고하면 알 수 있습니다. 이는 self, _cmd, name, ID, SEL, NSString.
그런 다음 프로그램은 forwardInvocation 메소드를 시작합니다. 획득된 키는 메소드 이름 setName:이며, [invocationgetArgument:&objatIndex:2]를 사용하여 매개변수 값을 획득합니다. 여기서는 "c++ 프라이머"입니다. 여기서 인덱스가 2여야 하는 이유는 무엇입니까? 앞서 분석한 대로 0번째 매개변수는 self, 1번째 매개변수는 _cmd, 2번째 매개변수는 메소드 뒤에 있는 매개변수이다.
마지막으로 변수 사전을 사용하여 값을 할당합니다. 이것으로 전체 setter 프로세스가 완료됩니다.
4) main.m에는 NSLog(@"%@", book.name);이라는 코드가 있습니다. 여기에서 프로그램을 실행하면 Book으로 이동합니다. m을 찾으려면 name이 값 방법입니다. 그러나 Book.m에는 그러한 값 메서드가 없으므로 프로그램은 메시지를 전달하기 위해 methodSignatureForSelector:를 입력합니다. 실행 후에는 "@@:"이 메소드 시그니처 유형으로 반환됩니다. 여기서 첫 번째 문자 @는 함수 반환 유형 NSString을 나타내고, 두 번째 문자 @는 self의 유형 id를 나타내며, 세 번째 문자:는 _cmd의 SEL 유형을 나타냅니다.
그런 다음 프로그램은 forwardInvocation 메소드를 시작합니다. 획득한 키는 메소드명 name 입니다. 마지막으로 이 키를 기반으로 사전에서 해당 값을 얻어 전체 getter 프로세스가 완료됩니다.
5) 코드를 디버깅하는 동안 name 및 작성자의 할당과 값만 methodSignatureForSelector: 및wardInvocation:을 입력하는 것을 발견했습니다. 두 가지 메소드 methodSignatureForSelector: 및forwardInvocation:을 입력하지 않는 속성 버전도 있습니다. 이는 version 속성이 @synthesize로 표시되고 컴파일러가 자동으로 setVersion 및 version 메서드를 추가하므로 메시지를 전달할 필요가 없기 때문입니다.
4. NSManagedObject의 하위 클래스에서 @dynamic 사용
@dynamic의 가장 일반적인 사용은 NSManagedObject에 있습니다. 프로그래밍 세터 및 게터. 그 이유는: @dynamic은 컴파일러에게 어떤 처리도 하지 않도록 지시하여 컴파일이 통과되도록 하기 때문입니다. getter 및 setter 메서드는 런타임에 동적으로 생성되고 Core Data 프레임워크는 이러한 속성에 대한 액세스 메서드를 생성합니다.