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 int
lub 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_SET
dodaje 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_GET
i 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 int
jako typu właściwości. Czyni to poprzez zawijanie wartości całkowitej do NSNumber
obiektu. 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
, BOOL
itp ...
Ograniczenia
Wszystkie makra są OBJC_ASSOCIATION_RETAIN_NONATOMIC
domyś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ę.