小技巧
- 我想知道有哪些方法插入到缓存中了
- 这里呢要打开隐藏文件夹的显示 shift + command + .
- 开始研究这个方法做了什么
测试一下这个方法能不能走
- 1.创建一个类声明一个未实现的方法
- 2.在.m文件中实现这个方法。
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
return nil;
}
-
3.虽然结果是报错的但是这个方法是调用的
-
4.现在创建另一个类并实现这个方法。
-
5.引入这个类,并将这个方法的返回值为新建对象
-
6.结果为成功的实现了另外的类的方法调用
-
OC调用方法的流程 通过 sel->imp
- 1.objc_msgSend 查找缓存
- 2.慢速查找 methodList
- 3.动态方法决议
- 4.runtime机制 让别的类调用同方法名的方法做这个事情。
快速转发
// 快速转发
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
return nil;
}
- (id)forwardingTargetForSelector:(SEL)aSelector{
return [LGStudent alloc];
}
- 加入我们所返回的类也没有这个方法的实现,则需要慢速转发 需要
methodSignatureForSelector方法配合forwardInvocation使用
慢速转发
//// 慢速转发
//返回一个方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
if (aSelector == @selector(sayHello)) {
//返回一个方法签名
return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
}
return [super methodSignatureForSelector:aSelector];
}
- 这个方法暂时不实现时
- (void)forwardInvocation:(NSInvocation *)anInvocation{
NSLog(@"%@ - %@",anInvocation.target,NSStringFromSelector(anInvocation.selector));
}
- 发现程序并没有奔溃同时记录了对象调用的方法。这里可以作为错误日志的搜集记录。
- 这里提示我们如果这个方法要实现就需要重写methodSignatureForSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation{
// NSLog(@"%@ - %@",anInvocation.target,NSStringFromSelector(anInvocation.selector));
LGStudent *s = [LGStudent alloc];
//判断我自己self 能够处理这个方法
if ([self respondsToSelector:anInvocation.selector]) {
[anInvocation invoke]; //直接调用invoke
}else if ([s respondsToSelector:anInvocation.selector]){
//判断别的类能够处理这个方法
[anInvocation invokeWithTarget:s];
}else{
//上传日志这里发生了奔溃
NSLog(@"%s - %@",__func__,NSStringFromSelector(anInvocation.selector));
}
}
探索思路,路是坎坷的,入门到放弃。
-
1.bt打印查看编译栈流程 发现目标在 CoreFoundation 中
-
2.搜索查找 CF源码无果
-
3.CoreFoundation 查找CoreFoundation开源源码
-
4.选择下载一个
最后找到一个CoreFoundation的开源动态库,哈哈哈哈哈哈我不会找。老师给的,网上找找应该是有的吧。
反汇编流程
- 将可执行文件给Hopper打开
-
进入 forwarding
- 这里是判断失误跳转到loc_64a67忽略不看
- 这里是判断失误跳转到loc_64a67忽略不看
-
结构存入到rax寄存器中。rax = _objc_msgSend(rdi,r14);
-
继续往下运行查找下层的消息接收者