通过ObjC类别重写一个方法并调用默认实现?

在使用类别时,可以使用自己的方式覆盖实现方法:

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

在包含类别networking结果“B”后调用方法“myMethod”。

myMethod类别实现调用原始类A myMethod最简单的方法是什么? 就我所知,您必须使用低级别的调用才能获得A类的原始方法钩子,然后调用它,但似乎在语法上会更简单。

如果你想要一个hackish的方式来做到这一点,涉及到的Objective-C运行时,你总是可以使用方法swizzling (在这里插入标准免责声明)。它将允许你存储不同的方法作为任意命名select器,然后交换运行时,因为你需要他们。

从comp.lang.objective-C FAQ列表 :“ 如果多个类别实现相同的方法呢?那么我们所知道的宇宙结构就不复存在了。实际上,这不是真的,但肯定会造成一些问题。当一个类实现了一个已经出现在一个类中的方法时(无论是通过另一个类,还是类的主@实现),该类的定义都会覆盖之前存在的定义,原来的定义不能再被Objective -C代码请注意,如果两个类别覆盖相同的方法,那么最后加载的是“胜利”,这在代码启动之前可能无法预测。

来自developer.apple.com :“当类别重写inheritance的方法时,类别中的方法可以像往常一样通过消息调用inheritance的实现,但是如果一个类别覆盖类别中已经存在的方法类,没有办法调用原来的实现“

看看我的文章有关在Mac开发人员库find的解决scheme: http : //codeshaker.blogspot.com/2012/01/calling-original-overridden-method-from.html

基本上,和上面的方法Swizzling一样,有一个简单的例子:

 #import <objc / runtime.h>

 @implementationtesting(logging)

 - (NSUInteger)logLength {
     NSUInteger长度= [自我logLength];
     NSLog(@“日志logging:%d”,长度);
    返回长度;
 }

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

 @结束

通过ConciseKit中包含的“helper”方法,你实际上调用了默认的实现…… 很奇怪,通过调用你的SWIZZLED实现..

你可以在+ (void) load中调用+ (BOOL)swizzleMethod:(SEL)originalSelector with:(SEL)anotherSelector in:(Class)klass; 即,

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

然后用混杂的方法,让我们假设它返回-(id) ..你可以做你的恶作剧,或者你是什么原因你摆在首位…然后,而不是返回一个对象,或self ,或不是。 。

 return [self swizzledHotness:yourSwizzledMethodsArgument]; 

正如这里所解释的

在这个方法中,它看起来像我们再次调用相同的方法,导致和无尽的recursion。 但到了这一行时,这两个方法已经交换了。 所以当我们调用swizzled_synchronize时,实际上是调用原始方法。

它的感觉和看起来很奇怪,但是..它的工作原理。 这使您可以为现有方法添加无穷无尽的装饰,并且仍然“调用超级”(实际上是自己的),并从原始方法的手工中获益…即使没有访问原始来源。