sunday1990 / BayMaxProtector

Crash protector -take care of your application like BayMax
MIT License
420 stars 55 forks source link

关闭防护好像有点问题 #7

Open ascendQing opened 6 years ago

ascendQing commented 6 years ago
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}];
    }

如果防护之前开启过,你会再执行一次交换操作,但是你并没有把交换后的方法和之前的方法换回来

sunday1990 commented 6 years ago

是这样的,拿UnrecognizedSelector类型防护为例子,如果之前有开启过防护的话,那么肯定会执行以下的代码: BMP_EXChangeInstanceMethod([NSObject class], @selector(forwardingTargetForSelector:), [NSObject class], @selector(BMP_forwardingTargetForSelector:)); 这时候,NSObject原有的forwardingTargetForSelector方法会被我们自己写的BMP_forwardingTargetForSelector方法替代,从而可以在我们自己的方法中执行一些保护措施,当关闭防护的时候,会首先通过imp链表判断下这个防护是不是开启过,如果没有开启过,就没有关闭的必要,如果有开启过的话,那么它会再执行一次交换操作,还是执行以下代码: BMP_EXChangeInstanceMethod([NSObject class], @selector(forwardingTargetForSelector:), [NSObject class], @selector(BMP_forwardingTargetForSelector:)); 但是这时候NSObject的forwardingTargetForSelector方法对应的imp其实已经跟NSObject分类中的BMP_forwardingTargetForSelector的imp发生互换了,此时再执行一次交换操作的话,相当于负负得正,又恢复原状了。

ascendQing commented 6 years ago

谢谢作者回复,昨晚上想明白了这个问题了。但是实际测试的时候,发现用block回调的方法打开防护后,再去关闭防护,然后再用block回调的方法打开防护,之后拦截UnrecognizedSelector类型就不起作用了。(防护类型都是所有类型)。暂时没有查出来问题。请作者帮忙看一下。谢谢。