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: Ignacio Enriquez <email@hidden>
- Date: Tue, 05 Mar 2013 14:43:27 +0900
> 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?
>
Originally I found that code in some tests where the testing class does not
expose some properties. (Probably the original developer didn't want to
expose a getter/setter just for testing purposes(?)
KVO is the first thing that came to my mind, but I wanted to make 100% sure
I understand why/how it is bad.
> > 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 ...
>
>
>
:)
--
Ignacio
_______________________________________________
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