47 votes

Remplacement d'une méthode via ObjC Catégorie et appeler l'implémentation par défaut?

Lors de l'utilisation de catégories, vous pouvez remplacer les méthodes de mise en œuvre avec votre propre comme suit:

// Base Class 
@interface ClassA : NSObject 
- (NSString *) myMethod;
@end
@implementation ClassA
- (NSString*) myMethod { return @"A"; }
@end

//Category
@interface ClassA (CategoryB) 
- (NSString *) myMethod;
@end
@implementation ClassA (CategoryB)
- (NSString*) myMethod { return @"B"; }
@end

L'appel de la méthode "myMethod" à la suite notamment de la catégorie des filets, le résultat "B".

Quel est le moyen le plus facile pour la Catégorie de mise en œuvre de myMethod à l'appel de la Classe d'origine Un myMethod? Aussi loin que je peux comprendre, vous auriez à utiliser le faible niveau des appels pour obtenir la méthode originale de crochet pour la Classe A et l'appeler, mais il me semblait qu'il y aurait un point de vue syntaxique de moyen plus facile de le faire.

37voto

cobbal Points 37900

Si vous voulez un hackish façon de faire qui consiste à coucher avec l'objective-c d'exécution, vous pouvez toujours utiliser la méthode swizzling (insérer des dénis ici.) Il vous permettra de stocker les différentes méthodes de arbitrariliy nommé sélecteurs, puis les swap au moment de l'exécution que vous en avez besoin.

19voto

Oren Trutner Points 12125

De comp.lang.objective-C FAQ inscription: "Que faire si plusieurs catégories de mettre en œuvre la même méthode? Puis le tissu de l'Univers tel que nous le connaissons n'existe plus. En fait, ce n'est pas tout à fait vrai, mais certainement quelques problèmes sera causé. Lorsqu'une catégorie implémente une méthode qui a déjà paru dans une classe (que ce soit par une autre catégorie ou de la classe primaire de @mise en œuvre), cette catégorie de la définition remplace la définition qui était déjà présent. La définition d'origine ne peut plus être atteint par le code Objective-C. Notez que si les deux catégories d'écraser la même méthode, puis selon ce qui a été chargée de la dernière "victoire", ce qui peut ne pas être possible de prévoir avant le code est lancé."

À partir de developer.apple.com: "Lorsqu'une catégorie prioritaire sur une méthode héritée, la méthode dans la catégorie, comme d'habitude, invoquer l'héritage de la mise en œuvre par l'intermédiaire d'un message de super. Toutefois, si une catégorie substitue une méthode qui existait déjà dans la catégorie de la classe, il est inutile d'invoquer la mise en œuvre originale"

12voto

Andras Points 196

Consultez mon article à propos d'une solution trouvée sur le Mac Développeur de la Bibliothèque: http://codeshaker.blogspot.com/2012/01/calling-original-overridden-method-from.html

En gros, c'est la même que la Méthode ci-dessus Swizzling avec un bref exemple:

#import <objc/runtime.h>

@mise en œuvre de Test (Enregistrement)

- (NSUInteger)logLength {
 NSUInteger longueur = [self logLength];
 NSLog(@"de connexion: %d", longueur);
 de retour de la longueur;
}

+ (void)charge {
 method_exchangeImplementations(class_getInstanceMethod(auto, @selector(longueur)), class_getInstanceMethod(auto, @selector(logLength)));
}

@end

1voto

alex gray Points 5089

Avec le swizzling "helper" méthodes incluses dans ConciseKit, vous avez réellement appeler l'implémentation par défaut... bizarrement assez.. en appelant votre SWIZZLED mise en œuvre..

Vous le mettez en place, en + (void) load, appelant + (BOOL)swizzleMethod:(SEL)originalSelector with:(SEL)anotherSelector in:(Class)klass;, c'est à dire

[$ swizzleMethod:@selector(oldTired:) 
            with:@selector(swizzledHotness:) in:self.class];

et puis, dans la swizzled méthode.. supposons qu'il retourne -(id).. vous pouvez faire votre méfait, ou quelle que soit la raison de votre swizzling en premier lieu... et puis, au lieu de retourner un objet, ou self, ou que sais-je encore..

return [self swizzledHotness:yourSwizzledMethodsArgument];

Comme expliqué ici...

Dans cette méthode, il semble que nous appelons la même méthode, encore une fois, cause et sans fin de la récursivité. Mais au moment où cette ligne est atteint, les deux méthodes ont été échangés. Ainsi, lorsque nous appelons swizzled_synchronize nous sommes en fait en appelant la méthode d'origine.

Il se sent et semble bizarre, mais.. il fonctionne. Cela vous permet d'ajouter sans fin des embellissements pour les méthodes existantes, et encore "appel super" (auto) et de récolter les avantages de la méthode originale de l'ouvrage... même sans accès à la source d'origine.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X