@implementation NSObject (Crash)
+ (void)load {
[self exchangeInstanceMethodWithOriginalSelector:@selector(methodSignatureForSelector:) swizzledSelector:@selector(crash_methodSignatureForSelector:)];
[self exchangeInstanceMethodWithOriginalSelector:@selector(forwardInvocation:) swizzledSelector:@selector(crash_forwardInvocation:)];
}
+ (void)exchangeInstanceMethodWithOriginalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
BOOL didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
- (NSMethodSignature *)crash_methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *methodSignature = [self crash_methodSignatureForSelector:aSelector];
NSLog(@"%s %@ %@ %@", __func__, NSStringFromClass([self class]), methodSignature, NSStringFromSelector(aSelector));
for (NSUInteger i = 0; i < methodSignature.numberOfArguments; ++i) {
NSLog(@"argument type %s", [methodSignature getArgumentTypeAtIndex:i]);
}
NSLog(@"return type %s", methodSignature.methodReturnType);
if ([NSStringFromClass([self class]) hasPrefix:@"xxx"] && methodSignature == nil) {
methodSignature = [self methodSignatureForSelector:@selector(crash_invokeWithInvocation:)];
}
return methodSignature;
}
- (void)crash_forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"%s %@ %@", __func__, NSStringFromClass([self class]), anInvocation);
NSLog(@"%@", anInvocation.target);
NSLog(@"%@", NSStringFromSelector(anInvocation.selector));
NSLog(@"%@", anInvocation.methodSignature);
for (NSUInteger i = 0; i < anInvocation.methodSignature.numberOfArguments; ++i) {
NSLog(@"argument type %s", [anInvocation.methodSignature getArgumentTypeAtIndex:i]);
}
NSLog(@"return type %s", anInvocation.methodSignature.methodReturnType);
NSInvocation *forwardInvocation = [NSInvocation invocationWithMethodSignature:anInvocation.methodSignature];
forwardInvocation.target = self;
forwardInvocation.selector = @selector(crash_invokeWithInvocation:);
[forwardInvocation setArgument:&anInvocation atIndex:2];
[forwardInvocation invoke];
}
- (void)crash_invokeWithInvocation:(NSInvocation *)anInvocation {
printf("########################\n");
printf("----- 警告:缺少方法 -----\n");
printf("方法:%s\n", NSStringFromSelector(anInvocation.selector).UTF8String);
printf("类:%s\n", NSStringFromClass([anInvocation.target class]).UTF8String);
printf("########################\n");
}
@end