13

我必须在这里object_getInstanceVariable工作,但它似乎只适用于浮点数、布尔值和整数,而不是双精度数。我确实怀疑我做错了什么,但我一直在绕圈子。

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在上面的函数返回 2 之前设置myIntValue为其他值getinstancevar,即。它已经改变了。

然后我尝试了

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

如果我这样做,ivar_getName(tmpIvar)我会得到“someDouble”,但myDoubuleValue = 0仍然!然后我尝试ivar_getTypeEncoding(tmpIvar)并得到应有的“d”。

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

我一定是在做一些我看不到的基本错误,所以如果有人能指出,我将不胜感激。

4

2 回答 2

30

object_getInstanceVariable是一个迷糊的小功能。据记载,最后一个参数是一个void **参数——也就是说,你传递一个void *变量的地址并获得一个指向实例变量的指针——但它的实现就像它是一个void *参数一样——也就是说,你传递一个变量的地址要保存实例变量副本的变量。问题是实现忽略了实例变量的大小,只是做了一个指针复制。所以任何与指针大小相同的东西都可以完美地工作。如果您在 32 位架构上运行,则只会复制高 32 位。long long(您也应该使用实例变量见证相同的行为。)

解决方案是使用主要 API,键值编码,使用-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"];
于 2009-08-02T21:43:59.863 回答
2

使用 valueForKey: 怎么样?

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

注意:这需要你有一个“someFloat”方法。如果你想使用 setValue:forKey:,你还需要 "setSomeFloat:" 方法。这很容易通过将 ivar 声明为 @property 并合成它来实现。

于 2009-08-02T17:00:21.793 回答