美文网首页
关于runtime方法调用(category同名函数问题)

关于runtime方法调用(category同名函数问题)

作者: 困在屋子里de猫 | 来源:发表于2018-07-26 17:44 被阅读16次

对于这个问题,其实平时用的非常少,很少有人会在扩展类里面加的是同名的方法。Xcode会在编译的时候对该扩展的同名方法给予警告(但这一般只是针对,你在不知情的状况下,为你的扩展类定义了与类中私有方法同名的方法……拗口)

同名方法警告

这种情况下调用该方法又会有什么结果呢?测试下来:

1.在该类的method_list中存在定义的多个同名函数

2.实际调用的时候会有两种情况:

    1)只存在一个扩展类的:实际调用的是扩展中的同名方法;

    2)存在多个扩展类的情况:实际调用到的哪个扩展类的方法要看load的order

Class的methodList,会遍历该类所有的扩展中的method_list 并添加更新类的method_list(并不会做同名的覆盖操作),所以我们取到的该类的methodList会有多个同名扩展的同名方法。

如下图,在objc_class被初始化的时候,调用_read_image方法,找到该类所有的扩展category。

_read_image方法

然后在attachCategories函数中将该类所有的扩展方法合并到class中的method_list:

attachCategories:方法

在class有扩展,且扩展有同名函数的时候,在调用该方法的时候:

从search_method_list方法中可以看到,method的查找是从前向后,找到后直接return,这也是为什么在调用该同名方法的时候,看起来像是覆盖了class中的method,其实只是因为category的方法在前面,被先search到后,直接返回。

search_method_list:方法

对于存在多个category,且都有同名方法的时候,具体会调用哪个呢?

注意attachCategories:方法的说明:

// Attach method lists and properties and protocols from categories to a class.

// Assumes the categories in cats are all loaded and sorted by load order, 

// oldest categories first.

从以上的说明中,可以看出,在多个扩展的情况下,category中的method加入class中的method_list中的顺序是根据load order的(但这也是一种假设assumes的情况),所以理论上在多个扩展情况下,最终调用的同名方法是哪一个,要看load order的顺序。我测试的结果是,创建的第一个category的method会被调用(也是符合上述假设:oldest categories first)。

这里只是心血来潮看下这种情况,一般不会有这种需求。如果需要修改class中的方法,可以hook到该函数class_getInstanceMethod(),利用method_exchangeImplementations(oldmethod, newmethod) 。

撸的源码是objc4-723……

理解上如果有不对的,也希望大家不吝指出哈

注意:OBJC2_UNAVAILABLE  表示在object2.0中被废弃的

参考文档:https://github.com/bestswifter/blog/blob/master/articles/objc-runtime.md

相关文章

网友评论

      本文标题:关于runtime方法调用(category同名函数问题)

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