읽기 전용 속성이 여전히 KVC로 쓰기를 허용하는 이유는 무엇입니까?
-
19-09-2019 - |
문제
저는 "Mac OS X용 프로그래밍"의 "키 값 코딩" 장을 진행하고 있습니다.저는 슬라이더와 레이블이 있는 인터페이스를 구축했습니다. 둘 다 int인 fido에 바인딩되어 있습니다.fido의 속성을 읽기 전용으로 설정한 경우에도 슬라이더를 움직이면 레이블의 값이 변경됩니다.나는 이것에 대해 일종의 오류가 발생할 것이라고 가정했습니다.속성이 읽기 전용인 경우 슬라이더가 여전히 속성에 쓸 수 있는 이유는 무엇입니까?나는 Setter가 생성되지 않고 KVC가 작동하지 않을 것이라고 생각했습니다.감사해요.
내가 사용하는 코드는 다음과 같습니다.
#import <Cocoa/Cocoa.h>
@interface AppController : NSObject
{
int fido;
}
@property (readonly, assign) int fido;
@end
#import "AppController.h"
@implementation AppController
@synthesize fido;
- (id)init
{
[super init];
[self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
NSNumber *n = [self valueForKey:@"fido"];
NSLog(@"fido = %@", n);
return self;
}
@end
대체 텍스트 http://idisk.me.com/nevan/Public/Pictures/Skitch/Window-20091001-174352.png
해결책
AppController.h :
@interface AppController : NSObject
{
int fido;
}
@property (readonly, assign) int fido;
@end
"AppController.h"가져 오기
@implementation AppController
@synthesize fido;
...
@end
이 시점에서, 당신은 AppController가 -fido
방법과 그 방법을 합성했습니다. 아니요 -setFido:
방법. 그렇다면 왜 다음과 같은 "일"합니까?
- (id)init
{
if (self=[super init]) {
[self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
NSNumber *n = [self valueForKey:@"fido"];
NSLog(@"fido = %@", n);
}
return self;
}
(BTW : 올바른 패턴을 구현하기 위해 -INIT를 수정했습니다)
이것은 KVC가 a를 따르기 때문에 작동합니다 휴리스틱 값을 설정하거나 얻습니다. 전화 -setValue:forKey:
먼저 찾습니다 -setFoo:
. 찾을 수없는 경우 인스턴스 변수를 찾습니다. foo
직접 설정합니다.
인스턴스 변수를 변경하면 참고하십시오 fido
에게 _fido
, 세트는 작동하지만 valueForKey
합성 된 방법을 호출 할 때 0을 반환합니다 (64 비트이기 때문에 @Synthesize는 합성 fido
인스턴스 변수. 혼란 스럽습니다.
Ivar의 이름을 변경한다면 bar
그리고 사용하십시오 @synthesize foo=bar;
, 런타임에 코드가 실패합니다.
당신은 볼 수:
2009-10-01 08:59:58.081 dfkjdfkjfjkfd[24099:903] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppController 0x20000e700> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key fido.'
*** Call stack at first throw:
(
0 CoreFoundation 0x00007fff85b055a4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff85c5a0f3 objc_exception_throw + 45
2 CoreFoundation 0x00007fff85b5caf9 -[NSException raise] + 9
3 Foundation 0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
(
0 CoreFoundation 0x00007fff85b055a4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x00007fff85c5a0f3 objc_exception_throw + 45
2 CoreFoundation 0x00007fff85b5caf9 -[NSException raise] + 9
3 Foundation 0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
4 dfkjdfkjfjkfd 0x0000000100000d96 -[AppController init] + 130
다른 팁
읽기 전용 속성이 있다는 것은 컴파일러가 해당 속성에 대한 설정자를 생성하지 않는다는 것을 의미합니다.KVO/KVC를 통해 쓰는 것은 여전히 합법적입니다.
컴파일러 지침 @property
그리고 @synthesize
문제의 변수를 얻고 설정하는 메소드를 작성하는 속기 방법입니다.
생성 된 세터 메소드의 이름이 지정되었습니다 setFido:
, 그리고 getter 방법의 이름이 지정되었습니다 fido
.
Readonly를 지정하면 컴파일러가 세터 메소드를 만들지 말고 getter 만 말하면 간단하게 알려줍니다. 변수를 다른 방법으로 설정하는 방식에 어떤 종류의 장벽도 두지 않습니다.
(내가 그 모든 것을 얻었 으면 좋겠어. 행운을 빌어 요!)