美文网首页
vicki753's iOS 基础--方法调用顺序

vicki753's iOS 基础--方法调用顺序

作者: vicki753 | 来源:发表于2018-08-02 15:04 被阅读13次

    再说说上面几个问题:

    • 你知道方法如何一层一层调用的么?
    根据参考链接,创建了一个项目检测,发现的确是先从类别方法优先调用, 创建的检测类.png

    调用的时候

    ZYNumberTestSubClass *subClass = [[ZYNumberTestSubClass alloc] init];
    [subClass checkTheThings];
    [subClass checkTheThingsWithParameters:@"hahahhahahah"];
    [ZYNumberTestSubClass useClassMethod];
    

    根据runtime的消息传递机制中的核心函数void objc_msgSend(id self, SEL cmd,...) 。

    经过打印:

    ZYNumberTestSubClass (ZY) -- checkTheThings --
    ZYNumberTestSubClass (ZY)--checkTheThingsWithParameters --hahahhahahah
    ZYNumberTestSubClass (ZY) --userClassMethod --
    可以看出,子类调用的时候是先走的类别中的方法。
    
    • 当类别中的方法不再实现的时候

      ZYNumberTestSubClass ======  checkTheThings ========
      ZYNumberTestSubClass ======  checkTheThingsWithParameters========hahahhahahah 
      ZYNumberTestSubClass ======  useClassMethod ========
      
    • 子类没有实现,类别也没有实现,就只有类方法有

       ZYNumberTest-- checkTheThings --
       ZYNumberTest--checkTheThingsWithParameters --      hahahhahahah--
       ZYNumberTest--userClassMethod --
      
    • 类方法也没有实现,运行报错:找不到方法

       Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ZYNumberTestSubClass checkTheThings]: unrecognized selector sent to instance 0x600000203970'
      

    “根据runtime的消息传递机制中的核心函数 void objc_msgSend(id self, SEL cmd,...) 来发送消息, 先从当前类中找调用的方法,若没有就继续去父类找,那么对于category重写同一个方法,则在消息传递的过程中,会最先找到category的方法从上至下顺序编译,编译时通过压栈的方式将多个分类压栈,根据后进先出的原则,后编译的会被先调用,当objc_msgSend找到方法并调用之后,就不再继续传递消息,所以形成所谓的覆盖,”

    ---------补充说明------------
    根据参考链接再详细的说明。
    首先是类方法还是实例方法,需要区分,如果是实例方法:
    1、首先是在相应操作的对象中的缓存方法中找到调用的方法,如果找到了转向实现并执行;
    如果是实例方法->在实例方法列表中,在相应操作的对象中的方法列表中找到并调用的方法,也就是实例方法的method_list[]中:

    _OBJC_$_CATEGORY_INSTANCE_METHODS_ZYNumberTestSubClass_$_ZY  ->看2
    

    如果是类方法->在类方法列表中没有找到,在相应操作的对象中的方法找到并调用方法,也就是类方法的method_list[]中:

    _OBJC_$_CATEGORY_CLASS_METHODS_ZYNumberTestSubClass_$_ZY。 ->看2
    

    2、如果当前对应的对象中的实例方法列表和类方法列表中都没有,就去父类找,这时候会发现如果子类没有实现父类的方法,那么上面的那个method_list[]里面就不会有对应的方法。
    3、如果这样到一直到根类都没找到,转向拦截调用,然后就是消息转发机制,runtime.
    4、如果没有重写拦截调用的方法,程序报错。

    参考链接:
    https://segmentfault.com/q/1010000007231260
    http://www.cocoachina.com/ios/20180110/21805.html
    https://www.jianshu.com/writer#/notebooks/4994894/notes/31626024

    • 方法找不到了会怎么样?它是如何找的?
      -之前有面试官问我如果找不到方法怎么办?我回答会崩,但是他似乎并不满意,好奇,改怎么回答。
    • 类的属性到底在哪儿?
    • block的结构对于类来说有哪些方式?

    相关文章

      网友评论

          本文标题:vicki753's iOS 基础--方法调用顺序

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