La réponse donnée fonctionne très bien et ma proposition n'est qu'une extension de celle-ci qui évite d'écrire trop de code passe-partout.
Afin d'éviter l'écriture répétée de méthodes getter et setter pour les propriétés de catégorie, cette réponse introduit des macros. De plus, ces macros facilitent l'utilisation des propriétés de type primitif telles que int
o BOOL
.
Approche traditionnelle sans macros
Traditionnellement, vous définissez une propriété de catégorie comme
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Ensuite, vous devez implémenter une méthode getter et setter en utilisant un fichier de type objet associé y el obtenir un sélecteur comme clé ( voir la réponse 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
L'approche que je propose
Maintenant, en utilisant une macro, vous allez écrire à la place :
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Les macros sont définies comme suit :
#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
ajoute un getter et un setter pour la propriété donnée. Les propriétés en lecture seule ou en écriture seule utiliseront la balise CATEGORY_PROPERTY_GET
y CATEGORY_PROPERTY_SET
macro respectivement.
Les types primitifs nécessitent un peu plus d'attention
Comme les types primitifs ne sont pas des objets, les macros ci-dessus contiennent un exemple d'utilisation de la fonction unsigned int
comme type de propriété. Pour ce faire, la valeur entière est enveloppée dans un fichier de type NSNumber
objet. Son utilisation est donc analogue à celle de l'exemple précédent :
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
En suivant ce modèle, vous pouvez simplement ajouter d'autres macros pour prendre également en charge les éléments suivants signed int
, BOOL
etc...
Limites
-
Toutes les macros utilisent OBJC_ASSOCIATION_RETAIN_NONATOMIC
par défaut.
-
Des IDE comme Code de l'application ne reconnaissent pas actuellement le nom du setter lors du remaniement du nom de la propriété. Vous devez le renommer vous-même.
2 votes
Pourquoi ne pas faire ce que vous faites normalement, mais au lieu d'une catégorie, ajouter la propriété à une classe de base MyClass ? Et pour aller plus loin, effectuez vos tâches lourdes en arrière-plan et faites en sorte que le processus déclenche une notification ou appelle un gestionnaire pour MyClass lorsque le processus est terminé.
4 votes
MyClass est une classe générée à partir de Core Data. Si je mets mon code objet personnalisé dans la classe générée, il disparaîtra si je régénère la classe à partir de mes données de base. Pour cette raison, j'utilise une catégorie.
1 votes
Acceptez peut-être la question qui correspond le mieux au titre ("Propriété dans la catégorie").
0 votes
Pourquoi ne pas simplement créer une sous-classe ?