利用runtime重写系统方法的两种方法

2016-08-17  本文已影响0人  我是一个TableView

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

猜你喜欢

热点阅读