Дана відповідь чудово працює, і моя пропозиція - лише розширення до неї, що дозволяє уникнути написання занадто великого кодового коду.
Щоб уникнути написання багаторазових методів getter та setter для властивостей категорії, ця відповідь вводить макроси. Крім того, ці макроси полегшують використання властивостей примітивного типу, таких як int
або BOOL
.
Традиційний підхід без макросів
Традиційно ви визначаєте категорію властивості типу
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Тоді вам потрібно реалізувати метод getter і setter, використовуючи асоційований об'єкт і селектор get як ключ ( див. Оригінальну відповідь ):
#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
додає getter та setter для даної властивості. Властивості лише для читання або для запису будуть використовувати відповідно 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, такі як Код додатка , в даний час не розпізнають ім'я налаштування під час рефакторингу імені ресурсу. Вам потрібно було б перейменувати його самостійно.