A resposta dada funciona muito bem e minha proposta é apenas uma extensão que evita escrever muito código clichê.
Para evitar escrever métodos getter e setter repetidamente para propriedades de categoria, esta resposta apresenta macros. Além disso, essas macros facilitam o uso de propriedades do tipo primitivo, como int
ou BOOL
.
Abordagem tradicional sem macros
Tradicionalmente, você define uma propriedade de categoria como
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Em seguida, você precisa implementar um método getter e setter usando um objeto associado e o seletor get como a chave ( consulte a resposta 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
Minha abordagem sugerida
Agora, usando uma macro, você escreverá:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
As macros são definidas da seguinte maneira:
#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)
A macro CATEGORY_PROPERTY_GET_SET
adiciona um getter e setter para a propriedade especificada. As propriedades somente leitura ou somente gravação usarão a macro CATEGORY_PROPERTY_GET
e, CATEGORY_PROPERTY_SET
respectivamente.
Tipos primitivos precisam de um pouco mais de atenção
Como os tipos primitivos não são objetos, as macros acima contêm um exemplo para uso unsigned int
como o tipo da propriedade. Isso é feito envolvendo o valor inteiro em um NSNumber
objeto. Portanto, seu uso é análogo ao exemplo anterior:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
Seguindo esse padrão, você pode simplesmente adicionar mais macros para também apoiar signed int
, BOOL
, etc ...
Limitações
Todas as macros estão sendo usadas OBJC_ASSOCIATION_RETAIN_NONATOMIC
por padrão.
IDEs como o App Code atualmente não reconhecem o nome do levantador ao refatorar o nome da propriedade. Você precisaria renomeá-lo sozinho.