2009-12-29 2 views
2

두 번 인스턴스 변수 값을 얻는 방법에 대한 예를 게시 할 수 있습니까? object_getIvar() 함수를 사용해 보았습니다.하지만이 함수는 스칼라 데이터 유형이 아닌 객체를 반환하는 변수에만 유용하기 때문에 잘 진행되지 않았습니다.Objective-C의 개체에서 Ivar 값 가져 오기

답변

11

인스턴스 변수의 이름을 이미 알고 있다면 KVC 만 사용할 수 있습니다. 객체 x의 double 값을 가지는 ivar가 "weight"라고하면, NSNumber* x=[obj valueForKey:@"weight"];을 수행하면 double 값을 [x doubleValue]까지 얻을 수 있습니다. 마찬가지로, double 값을 포함하는 NSNumber num을 [obj setValue:num forKey:@"weight"]으로 설정할 수 있습니다.

object_getIvar()은 수업 레이아웃을 얻거나 이름 만 알고있는 ivar의 유형 정보를 얻는 데 유용한 저급입니다. KVC가 충분하지 않은 경우 더 자세히 설명 할 수 있습니까? 정확히 무엇을 달성하고 싶습니까?

+0

매우 도움이되었습니다. 감사! KVC는 잘 작동했습니다. – ForeignerBR

5

나는 Yuji와 완전히 동의하고 KVC가 대다수의 문제에 대한 올바른 접근 방법이지만이 문제는 아마 너무 관련이있다. 당신이 정말로 ivars에서 파고 들기를 원하는 적은 수의 , 대답은 이것을 위해 object_getInstanceVariable()을 사용하는 것입니다.

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@interface MyObject : NSObject { 
    double _someDouble; 
} 
@property double someDouble; 
@end 
@implementation MyObject 
@synthesize someDouble=_someDouble; 
@end 

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    MyObject *object = [[MyObject alloc] init]; 
    object.someDouble = 3.14; 
    double doubleOut; 
    object_getInstanceVariable(object, "_someDouble", (void**)&doubleOut); 
    NSLog(@"%f", doubleOut); 
    [object release]; 
    [pool drain]; 
    return 0; 
} 

주의점 void**double*의 기괴한 캐스트 예를 들면 다음과 같습니다. 올바른 것이고 경고를 피하기 위해 필요하며 이는 객체 포인터를 반환하는 일반적인 유스 케이스의 부작용입니다.

하지만 정말은 거의 모든 경우에서 ivars에서 돌아 다니지 않아야합니다.

+0

예, 저는 지금이 경우에 Terminal.app의 플러그인이라고 생각합니다. classdump에서 TTView에 _clickedURL의 ivar이 있지만 속성을 공개하지 않는다는 것을 알고 있습니다. object_getInstanceVariable/object_setInstanceVariable이 필요한 것입니다. –

+0

KVC는 속성뿐만 아니라 ivars를 읽고 씁니다. –

7
/* 
set 
*/ 
Ivar ivar = class_getInstanceVariable([self class], "_rate"); 
((void (*)(id, Ivar, CGFloat))object_setIvar)(self, ivar, rate); 

/* 
get 
*/ 
ptrdiff_t offset = ivar_getOffset(ivar); 
unsigned char* bytes = (unsigned char *)(__bridge void*)self; 
CGFloat floatValue = *((CGFloat *)(bytes+offset));