利用OC的Runtime原理,我们可以实现MethodSwizzling
把一个我们未知其实现原理的方法进行扩展或者替换掉
+ (void)load
{
// 源方法--原始的方法
// 目的方法--我们自己实现的,用来替换源方法
static dispatch_once_t onceToken;
// MethodSwizzling代码只需要在类加载时调用一次,并且需要线程安全环境
dispatch_once(&onceToken, ^{
Class class = [self class];
// 获取方法的SEL
SEL origionSel = @selector(viewDidLoad);
SEL swizzlingSel = @selector(xxx_viewDidLoad);
// IMP origionMethod = class_getMethodImplementation(class, origionSel);
// IMP swizzlingMethod = class_getMethodImplementation(class, swizzlingSel);
// 根据SEL获取对应的Method
Method origionMethod = class_getInstanceMethod(class, origionSel);
Method swizzlingMethod = class_getInstanceMethod(class, swizzlingSel);
// 向类中添加目的方法对应的Method
BOOL hasAdded = class_addMethod(class, origionSel, method_getImplementation(swizzlingMethod), method_getTypeEncoding(swizzlingMethod));
// 交换源方法和目的方法的Method方法实现
if (hasAdded) {
class_replaceMethod(class, swizzlingSel, method_getImplementation(origionMethod), method_getTypeEncoding(origionMethod));
} else {
method_exchangeImplementations(origionMethod, swizzlingMethod);
}
});
}
这时候我们调用viewDidLoad方法就等于我们自己写的xxx_viewDidLoad方法
- (void)xxx_viewWillAppear:(BOOL)animated {
[self xxx_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}
这里调用xxx方法实际上是调用OC原来提供的方法,并不会造成死循环