重写系统方法并且还要调用原来的方法,我们经常使用的是继承。可是当场景不允许使用继承或使用继承不方便时,怎么办?这里介绍两种利用runtime和category重写系统方法的两种方法。我们这里使用重写ViewDidLoad方法为例。 首先创建一个UIViewController的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);
}));
});
}
复制代码