#import <objc/runtime.h>
#import <UIKit/UIKit.h>
static inline BOOL isClassContainSel(Class class, SEL sel) {
unsigned int count;
Method *methodList = class_copyMethodList(class,&count);
for (int i = 0; i < count; i++) {
Method method = methodList[i];
NSString *tempMethodString = [NSString stringWithUTF8String:sel_getName(method_getName(method))];
if ([tempMethodString isEqualToString:NSStringFromSelector(sel)]) {
return YES;
}
}
return NO;
}
static inline void _hook_exchangeMethod(Class originalClass, SEL originalSel, Class replacedClass, SEL replacedSel){
BOOL isContain = isClassContainSel(originalClass, originalSel);
if (!isContain) {
IMP imp = method_getImplementation(class_getInstanceMethod(originalClass, originalSel));
if (!imp) {
return;
}
class_addMethod(originalClass, originalSel, imp, nil);
}
Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
Method replacedMethod = class_getInstanceMethod(replacedClass, replacedSel);
IMP replacedMethodIMP = method_getImplementation(replacedMethod);
// 将样替换的方法往代理类中添加, (一般都能添加成功, 因为代理类中不会有我们自定义的函数)
BOOL didAddMethod =
class_addMethod(originalClass,
replacedSel,
replacedMethodIMP,
method_getTypeEncoding(replacedMethod));
if (didAddMethod) {// 添加成功
// 获取新方法在代理类中的地址
Method newMethod = class_getInstanceMethod(originalClass, replacedSel);
// 交互原方法和自定义方法
method_exchangeImplementations(originalMethod, newMethod);
}else{// 如果失败, 则证明自定义方法在代理方法中, 直接交互就可以
method_exchangeImplementations(originalMethod, replacedMethod);
}
}
typedef void (* _MFIMP)(id, SEL, ...);
typedef void (* _MFNIMP)(void);
@implementation UIViewControllerMethodHooker
BOOL MFObjCIsKindOf(Class cls, Class other)
{
while (cls != Nil)
{
if (cls == other)
{
return YES;
}
cls = class_getSuperclass(cls);
}
return NO;
}
+ (void)hook {
NSString *executablePath = [[NSBundle mainBundle] executablePath];
unsigned int classCount = 0;
const char **classNames = objc_copyClassNamesForImage([executablePath UTF8String], &classCount);
NSMutableArray *mutableArray = [NSMutableArray array];
for (int i = 0; i < classCount; i++) {
NSString *str = [NSString stringWithUTF8String:(classNames[i])];
[mutableArray addObject:str];
}
SEL sel = NSSelectorFromString(@"__mf_hook_after_initialize_");
Class VCClazz = [UIViewController class];
Class VCMeta = object_getClass(VCClazz);
BOOL containss = isClassContainSel(VCMeta, sel);
if (!containss) {
IMP imps = method_getImplementation(class_getClassMethod(self, @selector(__replace_initialize_implementation)));
if (!imps) return;
class_addMethod(VCMeta, sel, imps, nil);
}
NSArray *allControllers = [mutableArray copy];
[allControllers enumerateObjectsUsingBlock:^(NSString * _Nonnull className, NSUInteger idx, BOOL * _Nonnull stop) {
SEL sel_initialize = NSSelectorFromString(@"initialize");
Class meta = object_getClass(NSClassFromString(className));
Class clazz = NSClassFromString(className);
if (MFObjCIsKindOf(clazz, VCClazz)) {
BOOL contains = isClassContainSel(meta, sel_initialize);
if (!contains) {
IMP imp = method_getImplementation(class_getClassMethod(self, sel_initialize));
if (!imp) return;
class_addMethod(meta, sel_initialize, imp, nil);
}
// 经过上面的操作之后 必定在本类中有一个 initialize 方法的实现
Method iMethod = class_getInstanceMethod(meta, sel_initialize);
_MFIMP initialize0 = (_MFIMP)method_getImplementation(iMethod);
Method newMethod = class_getClassMethod(VCMeta, sel);
_MFIMP hook = (_MFIMP)method_getImplementation(newMethod);
dispatch_block_t block = ^() {
initialize0(clazz, sel_initialize);
hook(clazz, sel);
};
_MFNIMP p = (_MFNIMP )imp_implementationWithBlock(block);
method_setImplementation(iMethod, p);
[clazz description];
unsigned int count;
NSMutableArray *methods = [NSMutableArray array];
Method *methodList = class_copyMethodList(meta, &count);
for (int i = 0; i < count; i++) {
Method method = methodList[i];
NSString *tempMethodString = [NSString stringWithUTF8String:sel_getName(method_getName(method))];
[methods addObject:tempMethodString];
}
NSLog(@"%@__%@", NSStringFromClass(meta), methods);
}
}];
}
+ (void)__replace_initialize_implementation {
// 添加你的initialize方法hook代码
}
+ (void)initialize {
NSLog(@"_______________ hook添加的实现 %@", [self class]);
}
@end
网友评论