美文网首页
利用runtime重写系统方法的两种方法

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

作者: 我是一个TableView | 来源:发表于2016-08-17 15:17 被阅读0次

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

    相关文章

      网友评论

          本文标题:利用runtime重写系统方法的两种方法

          本文链接:https://www.haomeiwen.com/subject/xymmsttx.html