La respuesta dada funciona muy bien y mi propuesta es solo una extensión que evita escribir demasiado código repetitivo.
Para evitar escribir repetidamente métodos getter y setter para propiedades de categoría, esta respuesta introduce macros. Además, estas macros facilitan el uso de propiedades de tipo primitivas como int
o BOOL
.
Enfoque tradicional sin macros
Tradicionalmente, define una propiedad de categoría como
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Luego debe implementar un método getter y setter utilizando un objeto asociado y el selector get como clave ( consulte la respuesta original ):
#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
Mi enfoque sugerido
Ahora, usando una macro, escribirás en su lugar:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Las macros se definen de la siguiente manera:
#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
agrega un getter y setter para la propiedad dada. Las propiedades de solo lectura o de solo escritura usarán la macro CATEGORY_PROPERTY_GET
y CATEGORY_PROPERTY_SET
respectivamente.
Los tipos primitivos necesitan un poco más de atención.
Como los tipos primitivos no son objetos, las macros anteriores contienen un ejemplo para usar unsigned int
como tipo de propiedad. Lo hace envolviendo el valor entero en un NSNumber
objeto. Entonces su uso es análogo al ejemplo anterior:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
Siguiendo este patrón, simplemente puede añadir más macros para apoyar también signed int
, BOOL
, etc ...
Limitaciones
Todas las macros están usando OBJC_ASSOCIATION_RETAIN_NONATOMIC
por defecto.
Los IDEs como App Code actualmente no reconocen el nombre del configurador cuando refactorizan el nombre de la propiedad. Tendría que cambiarle el nombre usted mismo.