重写系统方法并且还要调用原来的方法,我们经常使用的是继承。可是当场景不允许使用继承或使用继承不方便时,怎么办?这里介绍两种利用runtime和category重写系统方法的两种方法。我们这里使用重写ViewDidLoad方法为例。
首先创建一个UIViewController的category。

category
方法一:
在category中重写load方法,并且实现一个customViewDidLoad方法。在load方法中获取viewDidLoad方法以及customViewDidLoad方法的IMP指针,并将其交换
+ (void)load{
Method method1 = class_getInstanceMethod([self class], @selector(customViewDidLoad));
Method method2 = class_getInstanceMethod([self class], @selector(viewDidLoad));
//交换method1和method2的IMP指针,(IMP代表了方法的具体的实现)
method_exchangeImplementations(method1, method2);
}
在customViewDidLoad中的[self customViewDidLoad]即为调用原viewDidLoad
- (void)customViewDidLoad{
[self customViewDidLoad];
NSLog(@"========%@ did load========",self);
}
方法二:
首先在category中定义一个函数指针类型:
typedef void (*_IMP)(id,SEL,...);
在category中重写load方法,在load方法中获取到viewDidLoad方法的函数指针,然后将原函数指针指向一个block,并且在block中使用之前获取到的函数指针调用原viewDidLoad方法。
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));
_IMP viewDidLoad_IMP = (_IMP)method_getImplementation(viewDidLoad);
method_setImplementation(viewDidLoad, imp_implementationWithBlock(^(id target, SEL action){
viewDidLoad_IMP(target,@selector(viewDidLoad));
NSLog(@"========%@ did load========",target);
}));
});
}