La risposta fornita funziona alla grande e la mia proposta è solo un'estensione che evita di scrivere troppo codice boilerplate.
Per evitare di scrivere ripetutamente metodi getter e setter per le proprietà delle categorie, questa risposta introduce delle macro. Inoltre, queste macro facilitano l'uso di proprietà di tipo primitivo come int
o BOOL
.
Approccio tradizionale senza macro
Tradizionalmente si definisce una proprietà di categoria come
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Quindi è necessario implementare un metodo getter e setter utilizzando un oggetto associato e il selettore get come chiave ( vedere la risposta originale ):
#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
Il mio approccio suggerito
Ora, usando una macro scriverai invece:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Le macro sono definite come segue:
#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)
La macro CATEGORY_PROPERTY_GET_SET
aggiunge un getter e un setter per la proprietà data. Le proprietà di sola lettura o di sola scrittura utilizzeranno rispettivamente la macro CATEGORY_PROPERTY_GET
e CATEGORY_PROPERTY_SET
.
I tipi primitivi hanno bisogno di un po 'più di attenzione
Poiché i tipi primitivi non sono oggetti, le macro precedenti contengono un esempio da utilizzare unsigned int
come tipo di proprietà. Lo fa avvolgendo il valore intero in un NSNumber
oggetto. Quindi il suo utilizzo è analogo all'esempio precedente:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
A seguito di questo modello, si può semplicemente aggiungere più macro per supportare anche signed int
, BOOL
, ecc ...
limitazioni
Tutte le macro vengono utilizzate OBJC_ASSOCIATION_RETAIN_NONATOMIC
per impostazione predefinita.
IDE come App Code attualmente non riconoscono il nome del setter durante il refactoring del nome della proprietà. Dovresti rinominarlo da solo.