对于这个问题,其实平时用的非常少,很少有人会在扩展类里面加的是同名的方法。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
网友评论