Данный ответ отлично работает, и мое предложение - это просто его расширение, позволяющее избежать написания слишком большого количества шаблонного кода.
Чтобы избежать многократного написания методов получения и установки для свойств категории, в этом ответе представлены макросы. Кроме того, эти макросы упрощают использование свойств примитивных типов, таких как 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, такие как App Code , в настоящее время не распознают имя установщика при рефакторинге имени свойства. Вам нужно будет переименовать его самостоятельно.