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

Ken*_*ner 47 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
Run Code Online (Sandbox Code Playgroud)

在包含类别之后调用方法"myMethod"将结果"B".

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

cob*_*bal 37

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

  • 这不一定是'hackish'的方式.Objective-C运行时是有原因的.这使得Objective-C优于其他编译语言. (11认同)
  • 链接到JRSwizzle代码:https://github.com/rentzsch/jrswizzle ...我喜欢这个,当你想要调整第三方库来做你喜欢的时候,方法调整是非常强大的! (3认同)

Ore*_*ner 19

来自comp.lang.objective-C FAQ列表:" 如果多个类别实现相同的方法怎么办呢?那么宇宙结构就像我们所知它不再存在.实际上,这不是真的,但肯定会引起一些问题.当类别实现已经出现在类中的方法时(无论是通过另一个类别,还是通过类'primary @implementation),该类别的定义将覆盖先前存在的定义.目标不再能够达到原始定义-C代码.请注意,如果两个类别覆盖相同的方法,则最后加载的是"胜利",这可能无法在代码启动之前进行预测."

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

  • 我可能不需要说,但为了以后的情况,对于未来的读者:一个类别实际上根本不像一个子类.`super`不会解析为'原始对象'. (2认同)

And*_*ras 12

查看我的文章,了解Mac开发人员库中找到的解决方案: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