Добавление свойств (с резервным хранилищем) возможно с использованием ObjectO-C ассоциированного объекта API. У меня даже есть небольшой макрос, который я написал для этой цели. Но до макро, вот что это будет выглядеть как «развернутый»:
#import <objc/runtime.h>
@interface UIViewController (SOAdditions)
@property (atomic, readwrite, copy) NSString* myProperty;
@end
static void * const kMyPropertyAssociatedStorageKey = (void*)&kMyPropertyAssociatedStorageKey;
@implementation UIViewController (SOAdditions)
- (void)setMyProperty:(NSString *)myProperty
{
objc_setAssociatedObject(self, kMyPropertyAssociatedStorageKey, myProperty, OBJC_ASSOCIATION_COPY);
}
- (NSString*)myProperty
{
return objc_getAssociatedObject(self, kMyPropertyAssociatedStorageKey);
}
@end
Вы можете найти documentation for associated storage here. Вы должны знать, что для использования связанных объектов существует ограничение производительности (скорость и память). Они - аккуратный трюк, но вы можете спросить себя, есть ли лучший способ сделать то, что вы пытаетесь сделать. (Опрятная часть трюка, если вы спросите меня, что среда выполнение будет обрабатывать -releases
на -dealloc
для Вас, в соответствии с политикой вы укажете, смотрите документацию для получения дополнительной информации.)
Теперь вот макрос:
#ifndef ASSOCIATED_STORAGE_PROPERTY_IMP
#define THREE_WAY_PASTER_INNER(a, b, c) a ## b ## c
#define THREE_WAY_PASTER(x,y,z) THREE_WAY_PASTER_INNER(x,y,z)
#define ASSOCIATED_STORAGE_PROPERTY_IMP(type, setter, getter, policy) \
static void * const THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter, __LINE__) = (void*)&THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter,__LINE__); \
\
- (type)getter { return objc_getAssociatedObject(self, THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter,__LINE__)); } \
\
- (void)setter: (type)value { objc_setAssociatedObject(self, THREE_WAY_PASTER(__ASSOCIATED_STORAGE_KEY_, getter,__LINE__) , value, policy); } \
#endif
Если вы поп, что в файле заголовка, то в приведенном выше примере можно свести к следующим образом:
#import <objc/runtime.h>
@interface UIViewController (SOAdditions)
@property (atomic, readwrite, copy) NSString* myProperty;
@end
@implementation UIViewController (SOAdditions)
ASSOCIATED_STORAGE_PROPERTY_IMP(NSString*, setMyProperty, myProperty, OBJC_ASSOCIATION_COPY)
@end
это должно пойти, не говоря о том, что политика (то есть сохраняют/копировать/назначить, атомное/nonatomic) вы объявляете в @property decl арация должна соответствовать политике, которую вы используете при использовании макроса (и/или вызываете базовый API, если вы не используете макрос), в противном случае вы закончите утечку памяти (или сбой).
Также , Я скажу еще раз за акцент. Этот трюк не является «бесплатным», поэтому, пожалуйста, не забудьте измерить производительность и убедитесь, что все выгоды, которые вы получаете, используя это, стоят того.
EDIT: Я собираюсь немного отступить от своих решительных и страшных предупреждений о штрафах за производительность связанного хранилища объектов. Существует штраф, но быстрое расследование говорит мне, что свойства, реализованные таким образом, не намного хуже, чем их @synthesized и эквивалентные ivar-эквиваленты. Тест немного надуман, но с 10 000 000 объектов, каждый из которых имеет 5 iVars с поддержкой ассоциативного хранения, я вижу ~ 30% медленную настройку производительности и получение. Это действительно не все так страшно, ИМХО. Я ожидал гораздо хуже. Время, затрачиваемое на управление памятью (сохраняет, копии), связанную с установленными операциями, затмевает накладные расходы из ассоциативных поисков.
Почему не подкласс 'UIViewController', а затем сделать все ваши другие подклассы наследуемыми от этого нового класса? Насколько вы уверены, что ивары являются общими для всех 'UIViewController'? - вполне возможно, что это не так, и вы в конечном итоге используете 'UIViewController' в качестве ведра для хранения всего, включая кухонную раковину, без причины. –
Потому что я не могу изменить, например, суперкласс «UITableViewControler». Однако я мог подклассифицировать каждый из подклассов UIViewController, но это не кажется правильным.Я уточню свой вопрос о распространенности. –