网易 crash保护
1.
@implementation NSObject(WMUnselectorExceptionHandler) + (void)wmcd_defend_handleUnrecognizerSelectorException { [WMRuntimeUtil exchangeInstanceSEL:@selector(forwardingTargetForSelector:) targetInstanceSEL:@selector(wmcd_defend_forwardingTargetForSelector:) aClass:self]; } - (id)wmcd_defend_forwardingTargetForSelector:(SEL)aSelector { if ([self wmcd_defend_shouldCatchUnselector] && ![self wmcd_defend_isInWMServiceStack]) { return [self wmcd_defend_objectForUnselector:aSelector]; } return [self wmcd_defend_forwardingTargetForSelector:aSelector]; } - (BOOL)wmcd_defend_shouldCatchUnselector { if([WMUnrecognizerSelectorExceptionHandler prefixArray].count == 0 && [WMUnrecognizerSelectorExceptionHandler classArray].count == 0) { return YES; } NSString *className = NSStringFromClass([self class]); __block BOOL needCatch = NO; [[WMUnrecognizerSelectorExceptionHandler prefixArray] enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) { NSRange range = [className rangeOfString:obj]; if(range.location == 0) { needCatch = YES; *stop = YES; } }]; [[WMUnrecognizerSelectorExceptionHandler classArray] enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) { if([className isEqualToString:obj]) { needCatch =YES; *stop = YES; } }]; return needCatch; } - (BOOL)wmcd_defend_isInWMServiceStack { NSArray *callStackSymbols = [NSThread callStackSymbols]; BOOL result = NO; for (NSString *callStatck in callStackSymbols) { if ([callStatck rangeOfString:@"+[WMService"].location != NSNotFound) { result = YES; break; } } return result; } - (id)wmcd_defend_objectForUnselector:(SEL)aSelector { _WMDefendUnselectorObject *defendObj = [[_WMDefendUnselectorObject alloc] init]; SEL swizzledSelector = @selector(wmcd_generalMethodForDefend); Method swizzleMethod = class_getInstanceMethod([_WMDefendUnselectorObject class], swizzledSelector); BOOL didAddMethod = class_addMethod([_WMDefendUnselectorObject class], aSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod)); NSString *log = [NSString stringWithFormat:@"self:%@, didAddMethod:%d, for unselector:%@", NSStringFromClass([self class]), didAddMethod, NSStringFromSelector(aSelector)]; [WMCrashLogger addCrashLogWithMessage:log]; return defendObj; } @end
https://github.com/iwm2017/WMCrashDefend
https://github.com/qiyer/QYCrashProtector
https://www.jianshu.com/p/02157577d4e7
2.apple ForwardInvocation
https://developer.apple.com/library/archive/navigation/
https://developer.apple.com/library/archive/samplecode/ForwardInvocation/Listings/main_m.html#//apple_ref/doc/uid/DTS40008833-main_m-DontLinkElementID_4
https://www.cnblogs.com/treejohn/p/3596531.html
3.
IMP是一个函数指针,指向相应的函数实现,函数一般会有2个默认参数:id类型的self和SEL类型的_cmd。平时我们之所以能在OC函数中调用self,也是因为函数中有隐藏起来了的self参数
https://www.jianshu.com/p/6dcb18161fbb