GNU Objective-C Runtime Trick

Can I, in the GNU Objective-C runtime, attach semi-arbitrary pieces of data to instance variables?

Problem:

I am currently working on a kind of Cocoa workalike for Linux, as a kind of pet project. (Please allow me not to be distracted by all the “use of GNUStep.” I know this, but it does not suit my needs. Moving ...) To do this, I am trying to combine a simple ORM system resembling DBIx :: Class for Perl. The general idea is to make the expression as simple (read: short) as possible, and if at all possible, without having to provide the +(id)constantClassAttribute methods for overriding.

The general idea is to declare my result classes as follows:

 @interface SomeTable : ORMResult { unsigned long long id; ORMResult *toOneRelation; ORMResultSet *toManyRelation; } @end 

Still such a dick. Now I can access these fields using [ORMResult self]->ivars and do all kinds of unpleasant things, such as automatically creating accessories, such as -[toManyRelation] or -[setToOneRelation] . A piece of cake. Unfortunately, there are two pieces of information that I cannot add using this setting; one is simple enough to solve, the other is not so much:

  • What is the actual class of results?

    This is solved by subclassing ORMResult (e.g. SomeTable ) and including it in there using runtime dynam (ag) ics to find out its value (toMany, toOne).

  • (And it's hard!) Is the attitude nullified?

    This is less easy to solve. My initial ideas were

    • (ab) using protocols, for example:

       @interface SomeTable : ORMResult { unsigned long long id; ORMResult <ORMNullable> *toOneRelation; } @end 

      This compiles, but unfortunately, when I try to use GDB to check ivars->ivar_list I find that the protocol information is not actually saved for the runtime of the game. This makes, I suppose, some twisted sense, since protocol declarations are mainly intended for the compiler.

    • Violation of protocol identifiers ( byref , bycopy and friends using define:

       @interface SomeTable : ORMResult { unsigned long long id; nullable OMRResult *toOneRelation; } @end 

      This has a pretty obvious flaw that actually doesn't work, as these are obvious that qualifiers only work in protocol declarations.

Thus, the question arises, how can this information be linked to Ivars in practice?

Note. As mentioned earlier, I use the GNU Objective-C runtime provided by GCC on Linux; not the one supplied by Apple!

Edit: Asterisk! I forgot about the central point: the alternative, of course, is to simply make all relationships nullified. I really don't want this, but if no other alternative exists, I assume that the path I will end in will go down.

+4
source share
2 answers

Well, as we did in the old days on Mac, it was creating a global variable containing an NSMutableDictionary into which we put the data that we want to bind to the object. Just use the string representation of the pointer as the key.

The only difficulty is figuring out when the object is gone, and make sure its entry in the dictionary is also deleted. You may need to resort to hacking as a swizzling -dealloc method to achieve this.

+2
source

You can see objc_setAssociatedObject and friends who allow you to attach arbitrary data to an object. However, I'm not sure if they are supported in the version of libobjc that you are using.

+1
source

Source: https://habr.com/ru/post/1313313/


All Articles