GNU Objective-C运行时技巧

时间:2010-06-20 14:14:27

标签: objective-c gcc metaprogramming objective-c-runtime

我可以在GNU Objective-C运行时中将半任意数据片段附加到实例变量吗?

挑战:

我目前正在研究一种针对Linux的Cocoa工作,作为一种宠物项目。 (拜托,让我们不要被所有“使用GNUStep”的东西所牵制。我知道它,但它不符合我的需要。继续......)为此,我试图拼凑一个简单的ORM系统,让人联想到用于Perl的DBIx :: Class一般的想法是使声明尽可能简单(阅读:简短),如果可能的话,不需要提供+(id)constantClassAttribute方法来覆盖。

一般的想法是按如下方式声明我的结果类:

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

@end

到目前为止,如此笨拙。我现在可以使用[ORMResult self]->ivars访问这些字段,并执行各种讨厌的操作,例如自动生成-[toManyRelation]-[setToOneRelation]等访问器。小菜一碟。不幸的是,我使用此设置无法添加两条信息;一个很容易解决,另一个不是很多:

  1. 实际的结果类是什么?

    这可以通过继承ORMResult(如SomeTable)并插入其中来解决  在那里,使用运行时动态(ag)来确定它是什么(toMany,toOne)。

  2. (这是一个棘手的问题!)关系是否可以为空?

    这不太容易解决。我最初的想法是

    1. (ab)使用协议,如下:

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

      这会编译,但不幸的是,当我尝试使用GDB来检查时 ivars->ivar_list条目我发现协议信息实际上没有保留 用于运行时玩具。我想,这会产生某种扭曲的感觉, 协议声明主要用于编译器。

    2. 使用定义滥用协议标识符(byrefbycopy和朋友:

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

      这具有相当明显的缺点,即不实际工作,因为这些 说明符显然只适用于协议方法声明。

  3. 那么,问题是如何在实践中将这些信息附加到伊娃身上?

    注意:如前所述,我正在使用由Linux上的GCC提供的 GNU Objective-C运行时;和不是Apple提供的那个!

    编辑:Starpox!我忘记了一个中心点:当然,另一种选择是简单地使所有关系成为可空的。我真的不想这样做,但如果没有其他选择,我想这就是我最终会走下去的道路。

2 个答案:

答案 0 :(得分:2)

好吧,我们以前在Mac上用来做这件事的方法是创建一个包含NSMutableDictionary的全局变量,我们将要附加的数据放入到该对象中。只需使用指针的字符串表示作为键。

唯一的困难是弄清楚一个物体何时消失并确保它的字典中的条目也被删除。您可能不得不求助于像方法调配-dealloc这样的hackery来实现这一点。

答案 1 :(得分:1)

您可以查看objc_setAssociatedObject和朋友,它们允许您将任意数据附加到对象。但是,我不确定您运行的libobjc版本是否支持它们。