Podana odpowiedź działa świetnie, a moja propozycja jest tylko jej rozszerzeniem, które pozwala uniknąć pisania zbyt wielu standardowych kodów.
Aby uniknąć wielokrotnego pisania metod pobierających i ustawiających dla właściwości kategorii, ta odpowiedź wprowadza makra. Dodatkowo te makra ułatwiają korzystanie z właściwości typów pierwotnych, takich jak intlub BOOL.
Tradycyjne podejście bez makr
Tradycyjnie definiujesz właściwość kategorii, taką jak
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Następnie musisz zaimplementować metodę pobierającą i ustawiającą, używając skojarzonego obiektu i selektora pobierania jako klucza ( patrz oryginalna odpowiedź ):
#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
Moje sugerowane podejście
Teraz, używając makra, napiszesz zamiast tego:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Makra są zdefiniowane w następujący sposób:
#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)
Makro CATEGORY_PROPERTY_GET_SETdodaje metodę pobierającą i ustawiającą dla danej właściwości. Właściwości tylko do odczytu lub tylko do zapisu będą używać odpowiednio makra CATEGORY_PROPERTY_GETi CATEGORY_PROPERTY_SET.
Trochę więcej uwagi wymagają typy prymitywne
Ponieważ typy pierwotne nie są obiektami, powyższe makra zawierają przykład użycia unsigned intjako typu właściwości. Czyni to poprzez zawijanie wartości całkowitej do NSNumberobiektu. Więc jego użycie jest analogiczne do poprzedniego przykładu:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
W następstwie tego wzorca, można po prostu dodać więcej makr również wspierać signed int, BOOLitp ...
Ograniczenia
Wszystkie makra są OBJC_ASSOCIATION_RETAIN_NONATOMICdomyślnie używane.
IDE, takie jak App Code , obecnie nie rozpoznają nazwy ustawiającego podczas refaktoryzacji nazwy właściwości. Musisz samodzielnie zmienić jego nazwę.