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

重写系统方法并且还要调用原来的方法,我们经常使用的是继承。可是当场景不允许使用继承或使用继承不方便时,怎么办?这里介绍两种利用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);
        }));
        
    });
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,860评论 0 9
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,721评论 33 466
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,386评论 30 472
  • 1,NSObject中description属性的意义,它可以重写吗?答案:每当 NSLog(@"")函数中出现 ...
    eightzg阅读 9,650评论 2 19
  • 自拟产品或服务,利用七种欲望中的愤怒、懒惰、贪婪和色欲分别写一句文案。 产品:智能毛绒玩具熊 1.愤怒:需要陪伴的...
    巍雅格格阅读 1,885评论 1 0