Re: getting ivar of fundamental types with object_getInstanceValue
Re: getting ivar of fundamental types with object_getInstanceValue
- Subject: Re: getting ivar of fundamental types with object_getInstanceValue
- From: Wim Lewis <email@hidden>
- Date: Mon, 04 Mar 2013 19:05:29 -0800
On 4 Mar 2013, at 6:23 PM, Ignacio Enriquez wrote:
> I am trying to understand the correct usage and caveats, of
> object_setInstanceValue function from objc/objc-runtime.h.
>
[....]
> An old post in this list (Re: ivars and fundamental types -
> http://lists.apple.com/archives/cocoa-dev/2010/Oct/msg00402.html) suggests
> its brother object_getInstanceValue function should not be used for
> fundamental types, only objects. "It happens to work for pointer-size
> non-object values -- Greg Parker". I am trying this in the iOS simulator
> and even though BOOL (size=1) and pointers (size=4) are not the same size
> it seems to work.
>
> What would be the best way to set the value of a ivar?
Is there a reason that properties, a setter method, or KVC won't work? If you absolutely need direct access, can you make the ivar public?
> It is still unclear to me, how is that object_getInstanceVariable only
> works for pointer-size things.
You can see the implementation of this if you download the runtime from opensource.apple.com and look in objc-class.m. object_{get,set}InstanceVariable() simply call object_{get,set}Ivar(), which take 'id's. They don't pay attention to the type of the ivar; they compute its offset and then assume there's an id there. So, in effect, they're doing this:
struct Foo {
Class isa;
...blah;
BOOL _somevar;
...blah;
}
id *varptr = (id *)&(someFoo->_somevar);
*varptr = (void *)YES;
In many cases this won't cause a problem because structure member alignment restrictions mean that the class's instance variables are all padded out to pointer-size boundaries. On a little-endian machine, retrieving the value and the padding, then casting to a narrower type, will (usually) actually do the right thing, as will the reverse operation ... but this only works through sheer chance. And if you change the types or ordering of your instance variables so that there isn't enough padding there (for example, if you have two BOOL instance variables, or perhaps if Apple changes the way the compiler lays out instance structures), then you'll start clobbering other ivars.
However, you can if you want use ivar_getOffset() to get the offset of an instance variable within an instance. I assume that something like this would work:
id foo;
Ivar ivar = class_getInstanceVariable(...);
*(some_random_type *)( ((void *)foo) + ivar_getOffset(ivar) ) = some_value;
(or maybe: memcpy(((void *)foo) + ivar_getOffset(ivar), &some_value, sizeof(some_value); )
although I've never been desperate enough to try it. If you find yourself doing this, I strongly suggest you consider the path that has brought you to this point and whether you could have done something differently. :)
If you look at objc-class.m, you'll see that there's another thing the above example doesn't do, which is interact correctly with ARC (or GC). Presumably that's OK, as long as your ivar isn't some compound type containing pointers ...
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden