Обман времени выполнения GNU Objective-C - PullRequest
4 голосов
/ 20 июня 2010

Могу ли я, во время выполнения GNU Objective-C, присоединить полу-произвольные фрагменты данных к переменным экземпляра?

Проблема:

В настоящее время я работаю над своего рода аналогом Cocoa для Linux, как своего рода любимый проект. (Пожалуйста, давайте не будем отвлекаться на все "использование GNUStep". Я знаю об этом, но это не соответствует моим потребностям. Двигаясь дальше ...) Для этого я пытаюсь собрать простую систему ORM, напоминающую DBIx :: Класс для Perl. Общая идея состоит в том, чтобы сделать объявление как можно более простым (читай: коротким) и, если это вообще возможно, без необходимости предоставления +(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. Злоупотребление идентификаторами протокола (byref, bycopy и друзьями, используя определения:

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

      Это имеет довольно очевидный недостаток: по-видимому, спецификаторы работают только в объявлениях метода протокола.

Тогда возникает вопрос, как можно на практике осуществить эту привязку информации к иварам?

Примечание: Как упоминалось изначально, я использую GNU Objective-C runtime , предоставляемый GCC для Linux; и не тот, который поставляется Apple!

Редактировать: Starpox! Я забыл центральный момент: альтернатива, конечно, состоит в том, чтобы просто сделать все отношения обнуляемыми. Этого я на самом деле не хочу, но если другой альтернативы не существует, я думаю, что это путь, по которому я в конечном итоге пойду.

Ответы [ 2 ]

2 голосов
/ 28 февраля 2011

Ну, как мы обычно делали это в старые времена на Mac, это создавали глобальную переменную, содержащую NSMutableDictionary, в которую мы помещаем данные, которые мы хотим прикрепить к объекту.Просто используйте строковое представление указателя в качестве ключа.

Единственная трудность заключается в том, чтобы выяснить, когда объект исчез, и убедиться, что его запись в словаре также удалена.Возможно, вам придется прибегнуть к хакерским методам, подобным методу swizzling -dealloc, чтобы добиться этого.

1 голос
/ 11 ноября 2010

Вы можете посмотреть на objc_setAssociatedObject и друзей, которые позволяют вам прикреплять произвольные данные к объекту. Однако я не уверен, что они поддерживаются в версии libobjc, которую вы используете.

...