Comme je ne peux pas créer une propriété synthétisée dans une catégorie en Objective-C, je ne sais pas comment optimiser le code suivant:
@interface MyClass (Variant)
@property (nonatomic, strong) NSString *test;
@end
@implementation MyClass (Variant)
@dynamic test;
- (NSString *)test {
NSString *res;
//do a lot of stuff
return res;
}
@end
La méthode de test est appelée plusieurs fois à l'exécution et je fais beaucoup de choses pour calculer le résultat. Normalement, en utilisant une propriété synthétisée, je stocke la valeur dans un IVar _test la première fois que la méthode est appelée, et je renvoie simplement cet IVar la prochaine fois. Comment puis-je optimiser le code ci-dessus?
Réponses:
La méthode de @ lorean fonctionnera (note: la réponse est maintenant supprimée) , mais vous n'auriez qu'un seul emplacement de stockage. Donc, si vous vouliez l'utiliser sur plusieurs instances et que chaque instance calcule une valeur distincte, cela ne fonctionnerait pas.
Heureusement, le runtime Objective-C a cette chose appelée Objets associés qui peut faire exactement ce que vous voulez:
la source
@selector(test)
comme clé, comme expliqué ici: stackoverflow.com/questions/16020918/...fichier .h
fichier .m
Tout comme une propriété normale - accessible avec la notation par points
Syntaxe plus simple
Vous pouvez également utiliser
@selector(nameOfGetter)
au lieu de créer une clé de pointeur statique comme ceci:Pour plus de détails, voir https://stackoverflow.com/a/16020927/202451
la source
@dynamic objectTag;
.@dynamic
signifie que le setter & getter seront générés ailleurs, mais dans ce cas ils sont implémentés ici.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 standard.
Afin d'éviter d'écrire à plusieurs reprises des 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 de propriétés de type primitif telles que
int
ouBOOL
.Approche traditionnelle sans macros
Traditionnellement, vous définissez une propriété de catégorie comme
Ensuite, vous devez implémenter une méthode getter et setter en utilisant un objet associé et le sélecteur get comme clé ( voir la réponse d'origine ):
Mon approche suggérée
Maintenant, en utilisant une macro, vous allez écrire à la place:
Les macros sont définies comme suit:
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 respectivement la macroCATEGORY_PROPERTY_GET
etCATEGORY_PROPERTY_SET
.Les types primitifs ont besoin d'un peu plus d'attention
Comme les types primitifs ne sont pas des objets, les macros ci-dessus contiennent un exemple à utiliser
unsigned int
comme type de propriété. Il le fait en enveloppant la valeur entière dans unNSNumber
objet. Son utilisation est donc analogue à l'exemple précédent:Suivant ce modèle, vous pouvez simplement ajouter des macros pour soutenir aussi
signed int
,BOOL
, etc ...Limites
Toutes les macros utilisent
OBJC_ASSOCIATION_RETAIN_NONATOMIC
par défaut.Les IDE comme App Code ne reconnaissent actuellement pas le nom du setter lors de la refactorisation du nom de la propriété. Vous devrez le renommer vous-même.
la source
#import <objc/runtime.h>
dans le fichier de catégorie .m sinon. erreur de compilation: la déclaration implicite de la fonction 'objc_getAssociatedObject' n'est pas valide en C99 . stackoverflow.com/questions/9408934/…Utilisez simplement la bibliothèque libextobjc :
fichier h:
m-fichier:
En savoir plus sur @synthesizeAssociation
la source
Testé uniquement avec iOS 9 Exemple: Ajout d'une propriété UIView à UINavigationBar (Category)
UINavigationBar + Helper.h
UINavigationBar + Helper.m
la source
Une autre solution possible, peut-être plus simple, qui n'utilise pas
Associated Objects
est de déclarer une variable dans le fichier d'implémentation de catégorie comme suit:L'inconvénient de ce type d'implémentation est que l'objet ne fonctionne pas comme une variable d'instance, mais plutôt comme une variable de classe. De plus, les attributs de propriété ne peuvent pas être attribués (comme ceux utilisés dans les objets associés comme OBJC_ASSOCIATION_RETAIN_NONATOMIC)
la source