Данный ответ прекрасно работает, и мое предложение является лишь его расширением, позволяющим избежать написания слишком большого количества стандартного кода.
Во избежание неоднократной записи методов получения и установки для свойств категории в этом ответе вводятся макросы.Кроме того, эти макросы упрощают использование свойств примитивного типа, таких как int
или BOOL
.
Традиционный подход без макросов
Традиционно вы определяете свойство категории как
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Затем вам нужно реализовать метод получения и установки, используя связанный объект и селектор получения в качестве ключа ( см. Оригинальный ответ ):
#import <objc/runtime.h>
@implementation MyClass (Category)
- (NSString *)text{
return objc_getAssociatedObject(self, @selector(text));
}
- (void)setText:(NSString *)text{
objc_setAssociatedObject(self, @selector(text), text, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
Мой предложенный подход
Теперь, используя макрос, вы напишите вместо этого:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Макросы определеныследующим образом:
#import <objc/runtime.h>
#define CATEGORY_PROPERTY_GET(type, property) - (type) property { return objc_getAssociatedObject(self, @selector(property)); }
#define CATEGORY_PROPERTY_SET(type, property, setter) - (void) setter (type) property { objc_setAssociatedObject(self, @selector(property), property, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
#define CATEGORY_PROPERTY_GET_SET(type, property, setter) CATEGORY_PROPERTY_GET(type, property) CATEGORY_PROPERTY_SET(type, property, setter)
#define CATEGORY_PROPERTY_GET_NSNUMBER_PRIMITIVE(type, property, valueSelector) - (type) property { return [objc_getAssociatedObject(self, @selector(property)) valueSelector]; }
#define CATEGORY_PROPERTY_SET_NSNUMBER_PRIMITIVE(type, property, setter, numberSelector) - (void) setter (type) property { objc_setAssociatedObject(self, @selector(property), [NSNumber numberSelector: property], OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
#define CATEGORY_PROPERTY_GET_UINT(property) CATEGORY_PROPERTY_GET_NSNUMBER_PRIMITIVE(unsigned int, property, unsignedIntValue)
#define CATEGORY_PROPERTY_SET_UINT(property, setter) CATEGORY_PROPERTY_SET_NSNUMBER_PRIMITIVE(unsigned int, property, setter, numberWithUnsignedInt)
#define CATEGORY_PROPERTY_GET_SET_UINT(property, setter) CATEGORY_PROPERTY_GET_UINT(property) CATEGORY_PROPERTY_SET_UINT(property, setter)
Макрос CATEGORY_PROPERTY_GET_SET
добавляет метод получения и установки для данного свойства.Свойства только для чтения или только для записи будут использовать макросы CATEGORY_PROPERTY_GET
и CATEGORY_PROPERTY_SET
соответственно.
Примитивные типы требуют немного большего внимания
Поскольку примитивные типыНи один объект не содержит приведенный выше макрос. Например, для использования unsigned int
в качестве типа свойства.Это достигается путем помещения целочисленного значения в объект NSNumber
.Таким образом, его использование аналогично предыдущему примеру:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
Следуя этой схеме, вы можете просто добавить больше макросов для поддержки signed int
, BOOL
и т. Д. *
Ограничения
По умолчанию все макросы используют OBJC_ASSOCIATION_RETAIN_NONATOMIC
.
IDE, такие как Код приложения в настоящее время не распознает имя сеттера при рефакторинге имени свойства.Вам нужно будет переименовать его самостоятельно.