Можно ли инициализировать свойство в категории до вызова любого метода категории?

Можно ли инициализировать свойство в категории?

Например, если у меня есть свойство изменяемого массива с именем nameList в классе. Возможно ли создать категорию для этого класса, чтобы добавить объект в свойство массива до вызова любого метода категории?


person Boon    schedule 20.02.2014    source источник


Ответы (3)


Если я правильно вас понимаю, а другие интерпретируют ваш вопрос по-разному, у вас есть:

  • Класс с собственностью
  • Категория этого класса

И вы хотите автоматически вызывать определенный метод перед вызовом любого метода категории для данного экземпляра, этот метод "инициализирует" методы категории, изменяя свойство.

Другими словами, вам нужен эквивалент подкласса с его методом init, но с использованием категории.

Если я правильно понимаю, то ответ - нет, инициализатора категории не существует. Поэтому перепроектируйте свою модель так, чтобы она не требовалась, что может заключаться в использовании подкласса, поскольку он обеспечивает то поведение, которое вам нужно.

Длинный ответ: вы можете попросить все методы категорий выполнить проверку, скажем, проверив свойство, которое вы собираетесь изменить, чтобы увидеть, есть ли у вас. Если проверка свойства не позволяет определить, был ли объект «инициализирован по категории», вы можете использовать связанный объект (см. Документацию по среде исполнения Apple) или какой-либо другой метод для записи этого факта.

HTH

Приложение: еще более долгое / более сложное решение ...

GCC и Clang поддерживают атрибут function (не метод) constructor, который отмечает функцию, которая должна быть вызвана во время загрузки, функция не принимает никаких параметров и ничего не возвращает. Так, например, предположим, что у вас есть класс Something и категория More, тогда в файле реализации категории, обычно называемом Something+More.m, вы можете написать:

__attribute__((constructor)) static void initializeSomethingMore(void)
{
   // do stuff
}

(static предотвращает глобальную видимость символа initializeSomethingMore, вы не хотите загрязнять глобальное пространство имен или иметь случайные вызовы этой функции - поэтому вы скрываете это.)

Эта функция будет вызываться автоматически, как и стандартный метод + (void) initialize класса. Что вы затем можете сделать, используя функции времени выполнения Objective-C, так это заменить назначенные методы экземпляра инициализатора класса Something вашими собственными реализациями. Они должны сначала вызвать исходную реализацию, а затем инициализировать вашу категорию перед возвратом объекта. В общих чертах вы определяете такой метод, как:

- (id) categoryVersionOfInit
{
    self = [self categoryVersionOfInit]; // NOT a mistake, see text!
    if (self)
    {
       // init category
    }
    return self;
}

а затем в initializeSomethingMore переключить реализации init и categoryVersionOfInit - так что любой вызов init в экземпляре Something фактически вызывает categoryVersionOfInit. Теперь вы видите причину явно саморекурсивного вызова в categoryVersionOfInit - к моменту его вызова реализации были переключены, поэтому вызов вызывает исходную реализацию _18 _... рисунок!)

Используя эту технику, вы можете «внедрить» код инициализации категории в класс. Обратите внимание, что точная точка, в которой вызывается ваша initializeSomethingMore функция, не определена, поэтому, например, вы не можете предположить, что она будет вызываться до или после любых методов, которые ваш целевой класс использует для инициализации (+ initialize, + load или его собственные функции-конструкторы).

person CRD    schedule 20.02.2014
comment
Вы все правильно поняли! Мое намерение для категории init состоит в том, чтобы категория могла регистрироваться в классе, чтобы класс использовал эту информацию осмысленным образом. - person Boon; 20.02.2014
comment
Я приму ваш ответ, поскольку вы его поняли, до тех пор, пока не будет найдено лучшее решение. Спасибо. - person Boon; 20.02.2014
comment
@Boon - добавлено дополнение, если вы действительно этого хотите! HTH - person CRD; 04.03.2014
comment
Это предложение о переключении реализаций метода (переключение селектора) и решило для меня эту проблему. Вот хороший пример того, как менять методы, как предлагается здесь: nshipster.com/method-swizzling - person BinaryNate; 28.08.2017

Конечно, это возможно с помощью objc/runtime и _2 _ / _ 3_
проверьте этот ответ

person Mykola Denysyuk    schedule 20.02.2014

Нет, это невозможно в цели c. Категория - это способ добавить только метод к существующему классу, в который вы не можете добавлять свойства. Прочитайте это

Почему я не могу @synthesize аксессуаров в категории?

person rahul    schedule 20.02.2014