阅读 55

iOS底层探索--消息转发机制

小谷底层探索合集

今天的博客来一波消息转发,可能最后会涉及到反汇编(兄弟们不要慌{刚开始我是最慌的😆},我们不需要全看懂他,我们只需要了解大致流程就行)

1. 代码分析

    1. 先搞一波,方法没有实现的代码
@interface XGTest : NSObject
- (void)testDemo;
@end
@implementation XGTest
@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        XGTest *test = [XGTest alloc];
        [test testDemo];
        
        NSLog(@"Hello, World!");
    }
    return 0;
}
复制代码

我们都知道的一件事情:它会崩~(不知道就运行下😆)

1.1. instrumentObjcMessageSends辅助分析

兄弟们先容我开一波上帝视角~(最后我会用反汇编证明)

    1. 上代码:
extern void instrumentObjcMessageSends(BOOL flag);

       instrumentObjcMessageSends(YES);
       [test testDemo];
       instrumentObjcMessageSends(NO);
复制代码
    1. 在调用方法前后加上instrumentObjcMessageSends,运行后在文件夹\tmp\下会产生一个msgSends-开头的文件

    1. 我们打开看下这个文件(log)

我们看出在动态方法决议之后,有走了一些方法~,但是我们不知道这个是啥?(其实就是快速转发和慢速转发~)

1.2. forwardingTargetForSelector分析

    1. 点进去之后

哈哈,这个时候,我就要推荐个东西了

所以么,英文也是可以搞定的😆。。

    1. 这个意思就是你可以找个接盘侠(看来有道词典也不人性化)
    1. 那我创建一个新的Class,让他去替他实现,看看可否
 @interface XGSubTest : NSObject
- (void)testDemo;
@end
@implementation XGSubTest
- (void)testDemo{
    NSLog(@"%s",__func__);
}
@end

@implementation XGTest

- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    return [XGSubTest alloc];
//    return [super forwardingTargetForSelector:aSelector];
}
@end
复制代码
    1. 看下输出

确实不崩溃了~

1.3. methodSignatureForSelector

我们刚才看到,走完快速查找之后也走了这个方法,我们继续可以通过苹果文档来找答案~(探索过程中其实有我们好多不知道的东西、我们只能通过文档、源码、反汇编去猜)

    1. 点进去

    1. 这个仔细看的话会发现一个关联方法

这次有道的翻译还行😆

那我们这次就不在forwardingTargetForSelector中处理了~,看看methodSignatureForSelector是否搞得定

    1. 我们要先看下文档里面说的返回值~

    1. 代码
@implementation XGTest

- (id)forwardingTargetForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    return [super forwardingTargetForSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    NSLog(@"%s - %@",__func__,NSStringFromSelector(aSelector));
    return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation{
    NSLog(@"%s - %@",__func__,anInvocation);
}

@end
复制代码
    1. 他的确走了,而且没有崩溃,不过有点美中不足~(看下输出)

    1. 嘿咻~,那我就要试试,是不是可以指定方法处理~

终于完美了这个感觉可以做好多事。runtime还是很强大~

2. 汇编验证

刚开始我们是开的上帝视角找到的forwardingTargetForSelectormethodSignatureForSelector

    1. 我们用反汇编验证下~:回到刚开始的状态,让他崩溃、然后看堆栈

    1. 我点击一下就可以看到~

    1. 我们第一反应就是找CoreFoundation的源码。。(这里我找过了。。找不到~)
    1. 那我们只能通过反汇编了~这里介绍个工具

可以找破解版。

    1. 我们找到编译的镜像文件( image list)

    1. 把他找到拖进Hopper

    1. 然后我们找到要观察的东西(全局搜索就可以定位到)

说实话,兄弟们这个东西不好截图

    1. 下面我就给兄弟们贴出必要的东西吧

    1. 这个时候我们还不能确定他走了methodSignatureForSelector,那我们看他goto之后走的流程~

    1. 这样我们也会知道,走完动态方法协议会走快速转发慢速转发

兄弟们~,画的有点乱凑合凑合😆