> 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 (Cocoa-dev@lists.apple.com) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com