4

我可以在 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]or -[setToOneRelation]。小菜一碟。不幸的是,我无法使用此设置添加两条信息;一个很容易解决,另一个不太简单:

  1. 实际结果类是什么?

    这可以通过子类化ORMResult(如SomeTable)解决,并将其插入其中,使用运行时动态(ag)ics 来确定它的一致性(toMany,toOne)。

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

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

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

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

      这可以编译,但不幸的是,当我尝试使用 GDB 检查 ivars->ivar_list条目时,我发现协议信息实际上并没有被保存以供运行时使用。我想这会产生某种扭曲的感觉,因为协议声明主要是针对编译器的。

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

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

      这有一个相当明显的缺点,即实际上不起作用,因为这些说明符显然只在协议方法声明中起作用。

那么,问题是如何在实践中消除这种对 ivars 的信息附加?

注意:正如最初提到的,我使用的是GNU Objective-C 运行时,由 Linux 上的 GCC 提供;而不是苹果提供的!

编辑:星痘!我忘记了一个中心点:当然,另一种选择是简单地使所有关系都可以为空。这我真的不想要,但如果没有其他选择存在,我想这就是我最终要走的路。

4

2 回答 2

2

好吧,过去我们在 Mac 上的做法是创建一个全局变量,其中包含一个 NSMutableDictionary,我们将要附加到对象的数据放入其中。只需使用指针的字符串表示形式作为键。

唯一的困难是弄清楚一个对象何时消失并确保它在字典中的条目也被删除。您可能不得不求助于类似方法 swizzling -dealloc 的hackery 来实现这一点。

于 2011-02-27T22:36:53.590 回答
1

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

于 2010-11-10T23:02:15.387 回答