美文网首页
关于IOS的消息转发

关于IOS的消息转发

作者: 宝家软件 | 来源:发表于2020-10-14 19:30 被阅读0次

    简单描述就是:

    消息转发就是实例对象或者类调用了方法后,都会转化成objc_msgSend的方式,给方法调用者发送了一条selector消息,通过isa查找类或父类的方法列表,如褁没有找到对应的方法,则通过动态方法解析和消息转发来补救,还不行则会crash。

    objc_msgSend具体还包含三个步骤:

    1.消息发送:

    在当前类或父类中查找方法,找到则存储他的imp(指向方法实现的指针);

    2.动态方法解析:

    如褁消息发送没有找到对应方法,则动态方法解析器开始工作,先判断当前cls对象是不是元类,也就是如果是对象方法会走到_class_resolveInstanceMethod,如过是类对象则会执行_class_resolveClassMethod,如过到最后没有查到,NSObject的resolveInstanceMethod会返回NO。

    #pragma mark - 动态方法解析 
    #比如有个run 方法没有声明和实现,增加方法后就不会出现找不到方法崩溃的问题了。
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        NSLog(@"动态方法解析 - %@",self);
        if (sel == @selector(run)) {
            // 我们动态解析对象方法
            NSLog(@"对象方法 run 解析走这里");
            SEL readSEL = @selector(readBook);
            Method readM= class_getInstanceMethod(self, readSEL);
            IMP readImp = method_getImplementation(readM);
            const char *type = method_getTypeEncoding(readM);
            return class_addMethod(self, sel, readImp, type);
        }
        return [super resolveInstanceMethod:sel];
    #此时只是给对象方法添加了一个imp,接下来再次进入查找imp流程,重复之前的操作,只不过现在对象方法已经有了imp,就会返回imp后继续执行
    
    3.消息转发;

    消息转发就是对方法进行替换了,具体可以看看https://www.jianshu.com/p/4f211020de05
    ,说明挺详细,能实现一些黑魔法的方式,比如里面提到的message的.m来实现VC的方法,这样可以提供.M给用户,但是重点方法保护起来。

    补充一点:runtime如何通过selector找到对应的IMP地址?

    每一个类对象中都一个对象方法列表(对象方法缓存)
    类方法列表是存放在类对象中isa指针指向的元类对象中(类方法缓存)。
    方法列表中每个方法结构体中记录着方法的名称,方法实现,以及参数类型,其实selector本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现。
    当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类对象方法列表里查找。
    当我们发送一个消息给一个类时,这条消息会在类的Meta Class对象的方法列表里查找。

    总结起来就是,类方法和对象方法都会存储成一个方法列表,通过selector方法用方法的名字来查找对应的实现。

    相关文章

      网友评论

          本文标题:关于IOS的消息转发

          本文链接:https://www.haomeiwen.com/subject/yhwwpktx.html