Runtime运行时机制在项目中的实际使用:
相信很多人都有过这样的经历,就是当我们接手一个项目时,若要修复某个BUG或是查看某某功能是如何实现的,特别是大项目,再加上对项目的业务逻辑不熟悉、对项目的设计架构不熟悉的情况下,我们往往感到无从下手,或是需要花一定的时间才能找出对应的类。
这篇博客就是为了需要让人感到蛋疼的问题而写的。
解决方案
给UIViewContoller建立一个分类,利用分类的特性,可以很好很方便地进行管理。类中原有的方法保持执行,还能扩展打印信息。
别忘了import < objc/runtime.h>
//load方法会在类第一次加载的时候被调用,调用的时间比较靠前。当类或分类被添加进运行时机制时就会调用。
//适合在这个方法里做方法交换,方法交换应该被保证在程序中只会执行一次。
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class selfClass = [self class];
SEL oriSel = @selector(viewWillAppear:);
Method oriMethod = class_getInstanceMethod(selfClass, oriSel);
//需要替换成能够输出日志的viewWillAppear
SEL currSel = @selector(logViewWillAppear:);
Method currMethod = class_getInstanceMethod(selfClass, currSel);
BOOL addSuccess = class_addMethod(selfClass,
oriSel,
method_getImplementation(currMethod),
method_getTypeEncoding(currMethod)
);
if (addSuccess) {
class_replaceMethod(selfClass, currSel, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
}
else {
//利用运行时机制,对方法进行调包交换。
method_exchangeImplementations(oriMethod, currMethod);
}
});
}
- (void)logViewWillAppear:(BOOL)animated {
NSString *classNameString = NSStringFromClass([self class]);
//此处进行过滤打印
if (![classNameString hasPrefix:@"Base"] && ![classNameString hasPrefix:@"Main"]) {
NSLog(@"当前控制器为:%@", classNameString);
}
//实际调用的是viewWillAppear
[self logViewWillAppear:animated];
}
@end