object_getInstanceVariable适用于float,int,bool,但不适用于double?

时间:2009-08-02 15:05:52

标签: objective-c return-value objective-c-runtime

我有object_getInstanceVariable作为here工作但是它似乎只适用于浮点数,布尔值和不是双打的。我确实怀疑自己做错了什么,但我一直在这么做。

float myFloatValue;
float someFloat = 2.123f;
object_getInstanceVariable(self, "someFloat", (void*)&myFloatValue);

有效,myFloatValue = 2.123

但是当我尝试

double myDoubleValue;
double someDouble = 2.123f;
object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);

我得到myDoubleValue = 0。如果我尝试在函数之前设置myDoubleValue,例如。 double myDoubleValue = 1.2f,当我在object_getInstanceVariable电话后阅读时,该值不变。在上面的myIntValue函数之前将getinstancevar设置为某个其他值将返回2,即。它已被改变。

然后我试了

Ivar tmpIvar = object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);

如果我ivar_getName(tmpIvar)我得到“someDouble”,但myDoubuleValue = 0仍然是!然后我尝试ivar_getTypeEncoding(tmpIvar)然后我得到“d”应该是。

总而言之,如果typeEncoding = float,它是有效的,如果是双精度型,则结果未设置但正确读取变量且返回值(Ivar)也正确。

我必须做一些我无法看到的基本错误,所以如果有人能够指出,我会很感激。

2 个答案:

答案 0 :(得分:29)

object_getInstanceVariable是一个混乱的小功能。最后一个参数是void **参数是documented,也就是说,您传递void *变量的地址并获取指向实例变量的指针 - 但它实现为它是一个void *参数 - 也就是说,您传递要保存实例变量副本的变量的地址。问题是实现忽略了实例变量的大小,只是执行指针复制。所以任何与指针大小相同的东西都能完美运作。如果您运行的是32位架构,则只会复制高32位。 (您应该看到与long long实例变量相同的行为。)

解决方案是使用主要API key-value coding,使用-valueForKey:

另一个解决方案:如果你想编写一个固定版本,比如作为NSObject的类别,它看起来像这样:

@implementation NSObject (InstanceVariableForKey)

- (void *)instanceVariableForKey:(NSString *)aKey {
    if (aKey) {
        Ivar ivar = object_getInstanceVariable(self, [aKey UTF8String], NULL);
        if (ivar) {
            return (void *)((char *)self + ivar_getOffset(ivar));
        }
    }
    return NULL;
}

@end

然后你的代码看起来像这样:

double myDoubleValue = *(double *)[self instanceVariableForKey:@"someDouble"];

答案 1 :(得分:2)

使用valueForKey怎么样??

NSNumber * value = [self valueForKey:[NSString stringWithUTF8String:ivar_getName(tmpIvar)]];
NSLog(@"Double value: %f", [value doubleValue];

注意:这要求您使用“someFloat”方法。如果你想使用setValue:forKey:,你还需要“setSomeFloat:”方法。通过将ivar声明为@property并将其合成,可以轻松实现这一点。