如何修改API中方法?

问题场景:如何统一修改viewController中的viewDidLoad方法,添加一句打印操作?

 

一、Method Swizzling解决

1、在viewController的分类中新增viewDidLoaded方法,方法内部调用类的viewDidLoad方法,并增加NSLog方法。

2、使用method_exchangeImplementation()交换viewDidLoaded和viewDidLoad方法。

#import "UIViewController+Print.h"
#import <objc/runtime.h> 

@implementation UIViewController (Print)

- (void)viewDidLoaded{
    [self viewDidLoaded];
    NSLog(@"Beche: %@ did load", self);
}

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));
        Method viewDidLoaded = class_getInstanceMethod(self, @selector(viewDidLoaded));
        method_exchangeImplementations(viewDidLoad, viewDidLoaded);
    });
}
@end

 

二、IMP解决

1、新建viewController的分类。

2、取得原始方法的IMP(implementation)指针。

3、重新设置方法实现。

typedef void (*_VIMP)(id,SEL,...); // 无返回值,有参数的IMP
typedef id (*_IMP)(id,SEL,...); // 有返回值,有参数的IMP

@implementation UIViewController (Print)

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 获取原始方法
        Method viewDidLoad = class_getInstanceMethod(self, @selector(viewDidLoad));
        // 获取原始方法实现
        _VIMP viewDidLoad_IMP = (_VIMP)method_getImplementation(viewDidLoad);
        method_setImplementation(viewDidLoad, imp_implementationWithBlock(^(id target,SEL action){
            // 调用原始方法实现
            viewDidLoad_IMP(target,@selector(viewDidLoad));
            // 增加代码
            NSLog(@"Beche: %@ did load", target);
        }));
    });
}
@end

 

posted on 2016-01-11 14:15  Beche  阅读(1895)  评论(0编辑  收藏  举报

导航