Substituir um método através da categoria ObjC e chamar a implementação padrão?

Ao usar categorias, você pode replace os methods de implementação pelos seus da seguinte forma:

// 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 

Chamando o método “myMethod” depois de include as redes de categoria, o resultado “B”.

Qual é a maneira mais fácil para a implementação de categoria do myMethod chamar o myMethod original de Classe A? Tão perto quanto eu possa descobrir, você teria que usar as chamadas de baixo nível para obter o gancho do método original para a Classe A e chamar isso, mas parecia que haveria uma maneira sintaticamente mais fácil de fazer isso.

Se você quiser uma maneira rápida de fazer isso que envolva o tempo de execução objective-c, você sempre pode usar swizzling de método (insira avisos de isenção padrão aqui). Ele permitirá que você armazene os diferentes methods como seletores nomeados arbitrariamente, então troque-os em tempo de execução como você precisa deles.

Da listview FAQ do comp.lang.objective-C : ” E se várias categorias implementarem o mesmo método? Então o tecido do Universo como o conhecemos deixa de existir. Na verdade, isso não é bem verdade, mas certamente alguns problemas serão causados. Quando uma categoria implementa um método que já apareceu em uma class (seja através de outra categoria, ou da class ‘primary @implementation), a definição dessa categoria sobrescreve a definição que estava presente anteriormente. A definição original não pode mais ser alcançada pelo Objetivo. -C – Observe que, se duas categorias sobrescreverem o mesmo método, a que tiver sido carregada por último “ganha”, o que pode não ser possível prever antes que o código seja iniciado. ”

Em developer.apple.com : “Quando uma categoria substitui um método herdado, o método na categoria pode, como de costume, invocar a implementação herdada através de uma mensagem para super. No entanto, se uma categoria replace um método que já existia na categoria class, não há como invocar a implementação original ”

Confira meu artigo sobre uma solução encontrada na Mac Developer Library: http://codeshaker.blogspot.com/2012/01/calling-original-overridden-method-from.html

Basicamente, é o mesmo que o Método Swizzling acima, com um breve exemplo:

 #import 

 @implementation Test (Registro)

 - (NSUInteger) logLength {
     NSUInteger length = [self logLength];
     NSLog (@ "Registrando:% d", comprimento);
     comprimento de retorno;
 }

 + (void) load {
     method_exchangeImplementations (class_getInstanceMethod (self, @selector (comprimento)), class_getInstanceMethod (self, @selector (logLength)));
 }

 @fim

Com o swizzling “helper” methods incluídos no ConciseKit , você realmente chama a implementação padrão … estranhamente .. chamando sua implementação SWIZZLED ..

Você configura em + (void) load , chamando + (BOOL)swizzleMethod:(SEL)originalSelector with:(SEL)anotherSelector in:(Class)klass; ou seja

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

e, em seguida, no método swizzled .. vamos supor que ele retorna -(id) .. você pode fazer o seu mal, ou seja qual for o motivo que você está swizzling em primeiro lugar … e, em seguida, em vez de retornar um object, ou self , ou outros enfeites. .

 return [self swizzledHotness:yourSwizzledMethodsArgument]; 

Como explicado aqui …

Nesse método, parece que estamos chamando o mesmo método novamente, causando uma recursion sem fim. Mas no momento em que esta linha é atingida, os dois methods foram trocados. Então, quando chamamos swizzled_synchronize, estamos realmente chamando o método original.

Parece e parece estranho, mas … funciona. Isso permite que você adicione embelezamentos infinitos aos methods existentes, e ainda “chame super” (na verdade, auto) e colha os benefícios da obra do método original … mesmo sem access à fonte original.