Objective-C: Propriété / variable d'instance dans la catégorie
Que je ne peux pas créer un synthétisé propriété dans une Catégorie Objective-C, je ne sais pas comment faire pour 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 d'essai-méthode est appelé plusieurs fois l'exécution et que je fais beaucoup de choses pour calculer le résultat. Normalement à l'aide d'un synthétisé bien je stocker la valeur dans un IVar _test la première fois, la méthode est appelée, et juste retour de ce IVar la prochaine fois. Comment j'ai optimisé le code ci-dessus?
- Pourquoi ne pas faire ce que vous le faites normalement, seulement au lieu d'une catégorie, ajouter la propriété à un MyClass de la classe de base? Et pour aller encore plus loin, effectuez votre lourd sur l'arrière-plan et le processus d'incendie à une notification ou d'appeler un gestionnaire pour MyClass lorsque le processus est terminé.
- MyClass est une classe générée à partir de Données de Base. Si je mais mon objet personnalisé code à l'intérieur de la classe générée, celle-ci disparaîtrait si je régénérer la classe à partir de ma Base de Données. De ce fait, je suis en utilisant une catégorie.
- Peut-être accepter la question qui s'applique le mieux pour le titre? ("De la propriété dans la catégorie")
- Pourquoi ne pas créer une sous-classe?
Vous devez vous connecter pour publier un commentaire.
@lorean de la méthode de travail (note: la réponse est maintenant supprimé), mais vous avez un seul emplacement de stockage. Donc si vous voulez l'utiliser sur plusieurs instances et chaque instance de calculer une valeur distincte, ça ne marcherait pas.
Heureusement, l'Objective-C runtime a cette chose appelée Les Objets Associés que peut faire exactement ce que vous êtes désireux:
@selector(test)
comme une clé, comme expliqué ici: stackoverflow.com/questions/16020918/....h-fichier
.m-fichier
Comme une propriété classique accessible avec dot notation
Plus facile de syntaxe
Vous pouvez également utiliser
@selector(nameOfGetter)
au lieu de créer un pointeur statique clés comme:Pour plus de détails, voir https://stackoverflow.com/a/16020927/202451
@dynamic objectTag;
.@dynamic
signifie que le setter & getter sera généré quelque part d'autre, mais dans ce cas, ils sont mis en œuvre ici.static void * LaserUnicornsPropertyKey
par défaut0
, de sorte que nous sommes en train de0
à objc_setAssociatedObject au lieu d'un pointeur unique qui est problématique lors de l'association de plusieurs propriétés de cette façon. Utilisation&LaserUnicornsPropertyKey
! (Voulu éditer le post pour résoudre ce problème, mais mon montage a été rejeté, quelqu'un peut-il résoudre ce problème?)#import <objc/runtime.h>
dans la catégorie .m fichier autrement. erreur de compilation: déclaration Implicite de la fonction "objc_getAssociatedObject' est pas valide en C99 vient. stackoverflow.com/questions/9408934/...La réponse qui est donnée fonctionne très bien et ma proposition est juste une extension de ce qui évite d'écrire trop de code réutilisable.
Afin d'éviter d'écrire à plusieurs reprises les méthodes getter et setter pour la catégorie des propriétés de cette réponse présente des macros. En outre, ces macros de faciliter l'utilisation de type primitif, des propriétés telles que
int
ouBOOL
.Approche traditionnelle sans macros
Traditionnellement vous définir une catégorie de la propriété comme
Alors vous avez besoin pour mettre en œuvre un getter et le setter de la méthode à l'aide d'un objet associé et la obtenir sélecteur de comme la clé (voir l'original de la réplique):
Mon approche suggérée
Maintenant, à l'aide d'une macro vous permettra d'écrire à la place:
Les macros sont définies comme suit:
La macro
CATEGORY_PROPERTY_GET_SET
ajoute un getter et setter de la propriété donnée. En lecture seule ou en écriture seule les propriétés de l'utilisation de laCATEGORY_PROPERTY_GET
etCATEGORY_PROPERTY_SET
macro respectivement.Types primitifs besoin d'un peu plus d'attention
Que les types primitifs sont pas les objets les macros ci-dessus contient un exemple d'utilisation d'
unsigned int
que le type de propriété. Il le fait par l'habillage de la valeur de l'entier dans unNSNumber
objet. De sorte que son utilisation est similaire à l'exemple précédent:En suivant ce modèle, vous pouvez simplement ajouter plus de macros à soutenir aussi
signed int
,BOOL
, etc...Limitations
Toutes les macros à l'aide de
OBJC_ASSOCIATION_RETAIN_NONATOMIC
par défaut.IDEs comme le Code de l'Application ne pas reconnaître le setter du nom lors d'un refactoring du nom de la propriété. Vous auriez besoin de le renommer par vous-même.
#import <objc/runtime.h>
dans la catégorie .m fichier autrement. erreur de compilation: déclaration Implicite de la fonction "objc_getAssociatedObject' est pas valide en C99 vient. stackoverflow.com/questions/9408934/...Suffit d'utiliser libextobjc bibliothèque:
h-fichier:
m-fichier:
Plus sur @synthesizeAssociation
Testé uniquement avec iOS 9
Exemple: l'Ajout d'une UIView propriété UINavigationBar (Catégorie)
UINavigationBar+Helper.h
UINavigationBar+Helper.m
Une autre solution possible, peut-être plus facile, ce qui ne veut pas utiliser
Associated Objects
est de déclarer une variable dans la catégorie de mise en œuvre de fichier comme suit:L'inconvénient de ce type de mise en œuvre est que l'objet ne fonctionne pas comme une variable d'instance, mais plutôt comme une variable de classe. Aussi, la propriété attributs ne peuvent pas être attribués(comme utilisé dans les Objets Associés comme OBJC_ASSOCIATION_RETAIN_NONATOMIC)