重写系统方法并且还要调用原来的方法,我们经常使用的是继承。可是当场景不允许使用继承或使用继承不方便时,怎么办?这里介绍两种利用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);
}));
});
}
网友评论