Question

if the variable in object_getIvar is a basic data type (eg. float, int, bool) how do I get the value as the function returns a pointer (id) according to the documentation. I've tried casting to an int, int* but when I try to get that to NSLog, I get error about an incompatible pointer type.

Was it helpful?

Solution

Getting:

myFloat = 2.34f;

float myFloatValue;
object_getInstanceVariable(self, "myFloat", (void*)&myFloatValue);

NSLog(@"%f", myFloatValue);

Outputs:

2.340000

Setting:

float newValue = 2.34f;
unsigned int addr = (unsigned int)&newValue;

object_setInstanceVariable(self, "myFloat", *(float**)addr);

NSLog(@"%f", myFloat);

Outputs:

2.340000

OTHER TIPS

For ARC:

Inspired by this answer: object_getIvar fails to read the value of BOOL iVar. You have to cast function call for object_getIvar to get basic-type ivars.

typedef int (*XYIntGetVariableFunction)(id object, const char* variableName);
XYIntGetVariableFunction intVariableFunction = (XYIntGetVariableFunction)object_getIvar;
int result = intVariableFunction(object, intVarName);

I have made a small useful macro for fast definition of such function pointers:

#define GET_IVAR_OF_TYPE_DEFININTION(type, capitalized_type) \
typedef type (*XY ## capitalized_type ## GetVariableFunctionType)(id object, Ivar ivar); \
XY ## capitalized_type ## GetVariableFunctionType XY ## capitalized_type ## GetVariableFunction = (XY ## capitalized_type ## GetVariableFunctionType)object_getIvar;

Then, for basic types you need to specify calls to macro (params e.g. (long long, LongLong) will fit):

GET_IVAR_OF_TYPE_DEFININTION(int, Int)

And after that a function for receiving int(or specified) variable type become available:

int result = XYIntGetVariableFunction(object, variableName)

The value that is returned is the value from the right place in the object; just not the right type. For int and BOOL (but not float), you could just cast the pointer to an int or BOOL, since pointers and ints are the same size and they can be cast to each other:

(int)object_getIvar(obj, myIntVar)

It's probably boxing the value in an NSNumber. You can verify this by NSLogging the returned id's className, like so:

id returnedValue = object_getIvar(self, myIntVar);
NSLog(@"Class: %@", [returnedValue className]);

Edit: I found another question just like this one here: Handling the return value of object_getIvar(id object, Ivar ivar)

From my own experimentation, it would appear that my original assumption was incorrect. int and float and other primitives appear to be returned as the actual value. However, it would be appropriate to use ivar_getTypeEncoding to verify that the returned value is the type that you're expecting it to be.

you can use object_getInstanceVariable directly: (haven't tested it)

void *ptr_to_result;
object_getInstanceVariable(obj, "intvarname", &ptr_to_result);
float result = *(float *)ptr_to_result;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top