Если я правильно вас понимаю, а другие интерпретируют ваш вопрос по-разному, у вас есть:
- Класс с собственностью
- Категория этого класса
И вы хотите автоматически вызывать определенный метод перед вызовом любого метода категории для данного экземпляра, этот метод "инициализирует" методы категории, изменяя свойство.
Другими словами, вам нужен эквивалент подкласса с его методом 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