通过ObjC类覆盖一个方法并调用默认实现?

时间:2009-07-06 04:53:50

标签: objective-c

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

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

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

myMethod的Category实现调用原始A类myMethod的最简单方法是什么?尽管我可以理解,你必须使用低级调用来获取A类的原始方法钩子并调用它,但似乎在语法上更容易实现这一点。

4 个答案:

答案 0 :(得分:37)

如果你想要一个hackish方法,这涉及到使用objective-c运行时,你总是可以使用method swizzling(在这里插入标准的免责声明。)它将允许你将不同的方法存储为任意命名的选择器,然后在运行时根据需要交换它们。

答案 1 :(得分:19)

来自comp.lang.objective-C FAQ listing:“如果多个类别实现相同的方法怎么办?那么我们所知道的宇宙结构就不复存在了。实际上,这不是真的,但肯定当一个类实现一个已经出现在类中的方法(无论是通过另一个类,还是类'primary @implementation)时,该类的定义会覆盖以前存在的定义。原始定义不能Objective-C代码可以更长时间。请注意,如果两个类别覆盖相同的方法,则最后加载的是“胜利”,这可能无法在代码启动之前进行预测。“

developer.apple.com:“当类别覆盖继承的方法时,类别中的方法可以像往常一样通过消息调用继承的实现到超级。但是,如果类别覆盖已存在的方法在类的类中,没有办法调用原始实现“

答案 2 :(得分:12)

查看我在Mac Developer Library上找到的解决方案的文章: http://codeshaker.blogspot.com/2012/01/calling-original-overridden-method-from.html

基本上,它与上面的方法Swizzling相同,只有一个简短的例子:

#import <objc/runtime.h>

@implementation Test (Logging)

- (NSUInteger)logLength {
    NSUInteger length = [self logLength];
    NSLog(@"Logging: %d", length);
    return length;
}

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

@end

答案 3 :(得分:1)

使用ConciseKit中包含的混合“帮助”方法,您实际上通过调用SWIZZLED实现来调用默认实现... 奇怪 ..

您在+ (void) load中进行了设置,呼叫+ (BOOL)swizzleMethod:(SEL)originalSelector with:(SEL)anotherSelector in:(Class)klass;,即

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

然后在混合的方法中..让我们假设它返回-(id) ..你可以做你的恶作剧,或者你在第一时间调整的任何理由......然后,而不是返回一个对象,或{ {1}},或者诸如此类..

self

As explained here…

  

在这个方法中,看起来我们再次调用相同的方法,导致无休止的递归。但到达此行时,两个方法已被交换。因此,当我们调用swizzled_synchronize时,我们实际上正在调用原始方法。

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