object_getInstanceVariable works for float, int, bool, but not for double?

后端 未结 2 1319
太阳男子
太阳男子 2020-12-28 20:19

I\'ve got object_getInstanceVariable to work as here however it seems to only work for floats, bools and ints not doubles. I do suspect I\'m doing something wro

相关标签:
2条回答
  • 2020-12-28 20:47

    object_getInstanceVariable is a confused little function. It is documented that the last parameter is a void ** parameter—that is, you pass the address of a void * variable and get a pointer to the instance variable—but it is implemented as if it was a void * parameter—that is, you pass the address of the variable that you want to hold a copy of the instance variable. The problem is that the implementation ignores the size of the instance variable and just does a pointer copy. So anything that's the same size as a pointer will work perfectly. If you're running on a 32-bit architecture, only the high 32 bits will be copied. (You should witness the same behavior with a long long instance variable as well.)

    The solution is to use the primary API, key-value coding, using -valueForKey:.

    The other solution: If you wanted to write a fixed version, say as a category for NSObject, it would look something like this:

    @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
    

    Then your code would look like this:

    double myDoubleValue = *(double *)[self instanceVariableForKey:@"someDouble"];
    
    0 讨论(0)
  • 2020-12-28 20:53

    What about using valueForKey:?

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

    Note: this requires you to have a "someFloat" method. If you want to use setValue:forKey:, you'll also need the "setSomeFloat:" method. This is easily implemented by declaring the ivar as an @property and synthesizing it.

    0 讨论(0)
提交回复
热议问题