Недавно мне нужно было это сделать (добавить состояние в категорию). @Dave DeLong имеет правильную точку зрения на это. Изучая лучший подход, я нашел отличный пост в блоге Тома Харрингтона. Мне нравится идея @ JeremyP об использовании объявлений @property в категории, но не его конкретная реализация (не фанат глобального синглтона или глобальные ссылки). Ассоциативные ссылки - путь.
Вот код для добавления (как представляется) иваров в вашу категорию. Я подробно писал об этом здесь .
В File.h вызывающая сторона видит только чистую высокоуровневую абстракцию:
@interface UIViewController (MyCategory)
@property (retain,nonatomic) NSUInteger someObject;
@end
В File.m мы можем реализовать @property (ПРИМЕЧАНИЕ: это не может быть @ synthesize'd):
@implementation UIViewController (MyCategory)
- (NSUInteger)someObject
{
return [MyCategoryIVars fetch:self].someObject;
}
- (void)setSomeObject:(NSUInteger)obj
{
[MyCategoryIVars fetch:self].someObject = obj;
}
Нам также нужно объявить и определить класс MyCategoryIVars. Для простоты понимания я объяснил это из правильного порядка компиляции. @Interface необходимо поместить перед реализацией Category @.
@interface MyCategoryIVars : NSObject
@property (retain,nonatomic) NSUInteger someObject;
+ (MyCategoryIVars*)fetch:(id)targetInstance;
@end
@implementation MyCategoryIVars
@synthesize someObject;
+ (MyCategoryIVars*)fetch:(id)targetInstance
{
static void *compactFetchIVarKey = &compactFetchIVarKey;
MyCategoryIVars *ivars = objc_getAssociatedObject(targetInstance, &compactFetchIVarKey);
if (ivars == nil) {
ivars = [[MyCategoryIVars alloc] init];
objc_setAssociatedObject(targetInstance, &compactFetchIVarKey, ivars, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[ivars release];
}
return ivars;
}
- (id)init
{
self = [super init];
return self;
}
- (void)dealloc
{
self.someObject = nil;
[super dealloc];
}
@end
Приведенный выше код объявляет и реализует класс, который содержит наши ivars (someObject). Поскольку мы не можем реально расширить UIViewController, это нужно сделать.