BayMaxProtector is a framework that can block common crashes , thereby enhancing your App's stability. Not only that, but you can also use the downgrade mechanism it provides to reduce a page that has a problem to a corresponding web page, So as not to affect the continuation of the business. 这是一个可以对常见崩溃进行拦阻,从而增强你App稳定性的框架,不仅如此,你还可以使用它提供的降级机制,将发生问题的页面降为对应的web页面,从而不影响业务的继续。
个人练手项目,存在一定风险,请谨慎使用
BayMax思路来自网易团队:大白健康系统--iOS APP运行时Crash自动修复系统
2.0主要是对1.0的升级与改造。
BayMaxDebugView
可以在开发中更直观的展示它所拦截到的异常,会展示捕获异常的数目,并且可以跟随手指移动,点击后可以展示错误的详细信息。收起后,错误信息清零,长按错误信息可以复制分享。
该功能主要用来帮助判断某些系统方法有没有被替换。
typedef struct IMPNode *PtrToIMP;
typedef PtrToIMP IMPlist;
struct IMPNode{
IMP imp;
PtrToIMP next;
};
/*向IMP链表中追加imp*/
static inline void BMP_InsertIMPToList(IMPlist list,IMP imp){
PtrToIMP nextNode = malloc(sizeof(struct IMPNode));
nextNode->imp = imp;
nextNode->next = list->next;
list->next = nextNode;
}
/*
递归判断IMP链表中有没有此元素。
*/
static inline BOOL BMP_ImpExistInList(IMPlist list, IMP imp){
if (list->imp == imp) {
return YES;
}else{
if (list->next != NULL) {
return BMP_ImpExistInList(list->next,imp);
}else{
return NO;
}
}
}
可以在任意页面,关闭或者打开防护功能,并且可以对重复操作进行过滤,重复的添加或者移除,会作为异常显示在debugView
中。
1、保存系统原有的IMP
static IMPlist impList;
+ (void)load{
//maping_ForwardingTarget_IMP为ForwardingTarget方法的映射
IMP maping_ForwardingTarget_IMP = class_getMethodImplementation([BayMaxProtector class], @selector(BMP_mappingForwardingTargetForSelectorMethod));
//maping_Timer_IMP为原有timer方法的映射
IMP maping_Timer_IMP = class_getMethodImplementation([BayMaxProtector class], @selector(BMP_mappingTimerMethod));
IMP KVO_IMP = class_getMethodImplementation([NSObject class], @selector(addObserver:forKeyPath:options:context:));
IMP notification_IMP = class_getMethodImplementation([NSNotificationCenter class], @selector(addObserver:selector:name:object:));
impList = malloc(sizeof(struct IMPNode));
impList->next = NULL;
BMP_InsertIMPToList(impList, maping_ForwardingTarget_IMP);
BMP_InsertIMPToList(impList, KVO_IMP);
BMP_InsertIMPToList(impList, maping_Timer_IMP);
BMP_InsertIMPToList(impList, notification_IMP);
}
2、根据操作的protectionType获取对应的IMP,然后判断该IMP在不在原有的impList中,在的话,说明该防护之前没有开启过,不在的话,说明该防护之前开启过。
if (!BMP_ImpExistInList(impList, imp)) {
NSLog(@"关闭保护");
//再执行一次交换操作
[self openProtectionsOn:protectionType catchErrorHandler:nil];
}else{//说明该方法没有被交换,即没有列在保护名单里,空处理即可
NSString * duplicateClose = [NSString stringWithFormat:@"[%@] Is Not In The Protection State Before And Don't Need To Close This Protection Again",protectionName];
[[BayMaxDebugView sharedDebugView]addErrorInfo:@{@"waring":duplicateClose}];
}
#pragma mark libobjc.A.dylib IMP映射
/**
NSObject ForwardingTargetForSelector方法的映射
*/
- (void)BMP_mappingForwardingTargetForSelectorMethod{
}
- (void)BMP_excMappingForwardingTargetForSelectorMethod{
}
/**
NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:方法的映射
*/
- (void)BMP_mappingTimerMethod{
}
- (void)BMP_excMappingTimerMethod{
}
如keypath重复监听、移除了未注册的观察者、移除了不存在的keypath,观察者未移除
退出页面时,timer
可以自动invalidate
在未移除监听者的时候,自动帮你移除监听者
可以通过配置在页面发生unrecognizedSelector
类型错误的时候,自动降级为对应的web页面,自动降级又分两种,一种是能拿到参数,然后拼成一个完整的url传给web,另一种是发生在viewdidload
中,且接收错误消息的对象不是视图控制器,这时候拿不到参数,只能拿到对应的url。】
在某些页面发生业务逻辑错误时,比如粗心的把价格单位“元”写成了“万元”,可以手动的将该页面将为对应的web页面,本质上是向该页面发送一个它不能够响应的消息,然后再走自动降级的逻辑。
- 手动:将
BayMaxProtector
下的所有文件拖入项目 CocoaPod
:podfile
加入pod 'BayMaxProtector'
//开启全部防护
[BayMaxProtector openProtectionsOn:BayMaxProtectionTypeAll catchErrorHandler:^(BayMaxCatchError * _Nullable error) {
//do your business
}];
//开启某一防护
[BayMaxProtector openProtectionsOn:BayMaxProtectionTypeUnrecognizedSelector];
//开启组合防护
[BayMaxProtector openProtectionsOn:BayMaxProtectionTypeUnrecognizedSelector|BayMaxProtectionTypeTimer];
//设置白名单
[BayMaxProtector ignoreProtectionsOnClassesWithPrefix:@[@"AV"]];
//同上
[BayMaxProtector closeProtectionsOn:BayMaxProtectionTypeAll];
[BayMaxProtector showDebugView];
[BayMaxProtector hideDebugView];
实现相对应的代理方法BayMaxDegradeAssistDelegate
与数据源协议BayMaxDegradeAssistDataSource
BayMax
在swift
环境下绝大部分功能仍然可用,但是如果在viewdidload
方法中发生unrecognizedSelector
类型的错误,这时候获取当前显示的视图控制器存在问题,从而会影响自动降级相关的流程,其他的暂时没发现问题,如果使用中有新的问题,请留言。
GitHub下载地址:BayMaxProtector