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.
5 Answers
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

- 1,410
- 12
- 20
-
2That doesnt work because you had a typo, if you change (void)&myFloatValue to (void *)&myFloatValue it works as advertised. – Russel West Aug 02 '09 at 03:59
-
Any ideas for object_setInstanceVariable for a float? I can get it to work for an int via int myInt = 5; int theInt; object_setInstanceVairable(self, "theInt", (void*)myInt); because pointers and ints are the same size, so it doesnt work for floats. – Russel West Aug 02 '09 at 08:32
-
it does indeed work :) thanks! Could please explain why you need *(float**)? I understand that (float**) is casting addr as a pointer to a pointer to which you then dereference. But since addr holds the address of newValue, isnt addr just like a pointer, hence you only need to cast it as float* and dereference that? That doesnt work but I dont understand why. What am I missing? – Russel West Aug 02 '09 at 12:39
-
unfortunately, `object_getInstanceVariable` and `object_setInstanceVariable` are unavailable in ARC – user102008 Apr 17 '14 at 02:31
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)

- 119,665
- 29
- 163
- 224
-
this appears to work however.... i can use a case on the typeEncoding to handle the bools and the ints but for the floats I'm still searching for a solution. – Russel West Aug 01 '09 at 20:19
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.

- 1
- 1

- 242,470
- 58
- 448
- 498
-
when I try to call [returnedValue className], I get warning no method className found. I then tried using object_getClassName(object_getIvar(self, myIntVar)) (myIntVar is actually allocated in a for loop so it changes) and the loop executes once and then I end up in GDB but there is no error logged. The only value that gets logged is 'nil'... ideas? – Russel West Aug 01 '09 at 20:01
-
@Russel I'm looking into it and experimenting. I'll edit my answer if I figure anything out. – Dave DeLong Aug 01 '09 at 21:04
-
Jacob got it to work using object_getInstanceVariable but I'm still curious about how to get object_getIvar to work because it is apparently faster ( http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/c/func/object_getIvar ) Tried searching the net for examples using it but nobody seems to use it with basic types. – Russel West Aug 02 '09 at 04:03
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;

- 119,665
- 29
- 163
- 224
-
I get incompatible pointer time on the 3rd argument.... I'm not terribly familiar with Obj-C I'm afraid. the docs say it should be a void pointer, thats the same as id i think? in which case i'm back to the same problem as above.... – Russel West Aug 01 '09 at 20:14
-
it now exits to GDB at the last line with no message as to why, compiles with no warnings however. If i hit continue at that line i get 'EXC_BAD_ACCESS' which I think is related to memory management. Any further thoughts? BTW I do check that my var typeEncoding = "f" before doing this so it cant be due to mismatch of variables/memory allocation etc. at least I dont think so. – Russel West Aug 02 '09 at 03:52