Die gegebene Antwort funktioniert großartig und mein Vorschlag ist nur eine Erweiterung, die vermeidet, zu viel Code auf dem Boilerplate zu schreiben.
Um zu vermeiden, dass wiederholt Getter- und Setter-Methoden für Kategorieeigenschaften geschrieben werden, werden in dieser Antwort Makros eingeführt. Zusätzlich erleichtern diese Makros die Verwendung primitiver Typeneigenschaften wie int
oder BOOL
.
Traditioneller Ansatz ohne Makros
Traditionell definieren Sie eine Kategorieeigenschaft wie
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Dann müssen Sie eine Getter- und Setter-Methode implementieren, die ein zugehöriges Objekt und den Get-Selektor als Schlüssel verwendet ( siehe ursprüngliche Antwort ):
#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
Mein vorgeschlagener Ansatz
Mit einem Makro schreiben Sie stattdessen:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Die Makros sind wie folgt definiert:
#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)
Das Makro CATEGORY_PROPERTY_GET_SET
fügt einen Getter und einen Setter für die angegebene Eigenschaft hinzu. Read-only oder Nur - Schreib-Eigenschaften werden die Verwendung CATEGORY_PROPERTY_GET
und CATEGORY_PROPERTY_SET
jeweils Makro.
Primitive Typen brauchen etwas mehr Aufmerksamkeit
Da primitive Typen keine Objekte sind, enthalten die obigen Makros ein Beispiel für die Verwendung unsigned int
als Eigenschaftstyp. Dazu wird der ganzzahlige Wert in ein NSNumber
Objekt eingeschlossen. Die Verwendung ist also analog zum vorherigen Beispiel:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
Nach diesem Muster können Sie einfach mehr Makros auch hinzufügen , zu unterstützen signed int
, BOOL
usw ...
Einschränkungen
Alle Makros werden OBJC_ASSOCIATION_RETAIN_NONATOMIC
standardmäßig verwendet.
IDEs wie App Code erkennen derzeit den Namen des Setters nicht, wenn der Name der Eigenschaft umgestaltet wird. Sie müssten es selbst umbenennen.