2009-12-29 11 views
2

有人可以發表我如何獲得實例變量值的例子嗎? 我嘗試過使用object_getIvar()函數,但那樣做並不好,因爲它看起來像這個函數只適用於返回對象而不是標量數據類型的變量。從Objective-C中的對象獲取Ivar值

回答

11

如果您已經知道實例變量的名稱,則可以使用KVC。用一個物體的雙倍值來說伊娃,稱爲「重量」,你做NSNumber* x=[obj valueForKey:@"weight"];然後你可以通過[x doubleValue]得到雙倍值。 同樣,您可以通過[obj setValue:num forKey:@"weight"]來設置包含雙倍值的NSNumber num。

object_getIvar()object_getIvar()是較低層次的東西,有助於獲得類佈局和/或獲取只知道名稱等的伊娃類型信息。如果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; 
} 

double*怪異強制轉換爲void**。它是正確的,需要避免警告,並且是通常用例返回對象指針的副作用。

但是你真的不應該在所有的情況下,而是在極少數情況下,在所有的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));