+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originSEL = @selector(viewWillAppear:);
SEL swizzleSEL = @selector(xx_viewWillAppear:);
Method originMethod = class_getInstanceMethod([self class], originSEL);
Method swizzleMethod = class_getInstanceMethod([self class], swizzleSEL);
/*给原来的方法添加实现
如果添加成功则说明该类中没有实现原方法, 同时也为该原方法添加了实现(本例中的`viewWillAppear:`方法不存在这个问题)
如果添加失败, 说明该类中已经有了原方法的实现, 直接交换方法即可
*/
BOOL addSucceed = class_addMethod([self class], originSEL, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (addSucceed) {
//添加成功
class_replaceMethod([self class], swizzleSEL, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
}else {
//添加失败
method_exchangeImplementations(originMethod, swizzleMethod);
}
});
}
- (void)xx_viewWillAppear:(BOOL)animated {
//这里调用自己不会造成死循环, 看似是调用自己, 实则调用的是`viewWillAppear:`的实现
[self xx_viewWillAppear:animated];
NSLog(@"xx_viewWillAppear");
}
image.png
-
之所以选在
load
方法中去实现, 是因为load
在文件加载的时候就会被调用, 甚至早于main
函数, 这样不会出现原方法被调用的时候, 还没交换的情况 -
用
dispatch_once_t
就是保证这段代码只执行一次
网友评论