category 方法调用的顺序
来源:互联网 发布:相同格式表格数据合并 编辑:程序博客网 时间:2024/06/07 04:08
一、category重写主类方法
在项目中我们经常会使用category(类别)来为已有的类添加新的方法。我们知道,如果我们重写原有类的方法,则类别的方法会替换掉原有类的方法,并且类别中会有警告的信息
原方法失效,分类方法生效的原理是什么?
这里看一下类的初始化,首先oc是动态语言,建立在runtime 的基础上,同样类的初始化也是动态的,根类NSObject 的+load 和+initilize两个方法,用于类的初始化,我们这里要着重看的是+load方法:
+load 方法是当类或分类被添加到 Objective-C runtime 时被调用的,实现这个方法可以让我们在类加载的时候执行一些类相关的行为。子类的 +load 方法会在它的所有父类的 +load 方法执行之后执行,而分类的 +load 方法会在它的主类的 +load 方法执行之后执行。
原因就在这里,因为加载顺序是父类先+load,然后子类+load,然后分类+load,那么如果分类重写子类方法:首先子类+load,将方法添加到类的方法列表methodLists,然后分类+load,将重写的方法添加到方法列表中,但是这里存在几点疑问:
A. 方法列表methodLists里是否会有两个SEL相同的方法?
B. 如果会有,这两个方法在方法列表中的顺序是怎样的?(顺序决定哪个被调用)
到这里很多人会猜:methodList 里面会有两个SEL 相同的方法名,但执行其中一个
#import "likeObj.h"@implementation likeObj-(void)test { NSLog(@"原来的类");}@end#import "likeObj+likeCate.h"@implementation likeObj (likeCate)-(void)test { NSLog(@"类别的类");}@end//使用Runtime 来查看方法#import "ViewController.h"#import <objc/runtime.h>#import "likeObj.h"#import "likeObj+likeCate.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; likeObj * li = [[likeObj alloc]init]; [li test]; id obj = objc_getClass("likeObj"); unsigned int count ,i; Method *methodList = class_copyMethodList(obj, &count); for ( i =0 ; i< count; i++) { Method method = methodList[i]; NSLog(@"------%@",NSStringFromSelector(method_getName(method))); }}@end// 打印为2017-11-16 20:06:16.671 categoryDemo[6420:2222139] 类别的类2017-11-16 20:06:18.781 categoryDemo[6420:2222139] ------test2017-11-16 20:06:19.417 categoryDemo[6420:2222139] ------test
由代码可以看出,猜想是对的
可见:
1. 方法列表里会存在两个SEL相同的方法。
2. 实际调用时,调用的是后添加的方法,即后添加的方法在方法列表methodLists的这个数组的顶部
后+load的类的方法,后添加到方法列表,而这时的添加方式又是插入顶部添加,即[methodLists insertObject:category_method atIndex:0]; 所以objc_msgSend遍历方法列表查找SEL 对应的IMP时,会先找到分类重写的那个,调用执行。然后添加到缓存列表中,这样主类方法实现永远也不会调到。
二、多个category实现同一个方法
多个分类同时重写同一个方法,执行顺序又是怎样的呢?
对于多个分类同时重写同一个方法,Xcode在运行时是根据buildPhases->Compile Sources里面的顺序从上至下编译的,就像子类和分类一样,后编译的后+ load,即后添加到方法列表,所以后编译的分类,方法会放到方法列表顶部,调用的时候先执行
(所以会先调用下面的类的方法,此时如果你鼠标拖动两个类别的顺序,会随着你拖动的顺序改变的)
总结一句话: 类的加载顺序,决定方法的添加顺序,调用的时候,后添加的方法会先被找到,所以调用的始终是后加载的类的方法实现。
- category 方法调用的顺序
- 【iOS】category重写方法的调用
- 040.category 调用私有方法
- 040.category 调用私有方法
- didLoadFromCCB方法的调用顺序
- listview方法的调用顺序
- 构造方法的调用顺序
- java中构造方法的调用顺序
- Java方法调用的优先顺序
- AsyncTask内的各个方法调用顺序:
- AsyncTask内的各个方法调用顺序
- AsyncTask内的各个方法调用顺序
- Java中多态的方法调用顺序问题
- java构造方法的调用顺序
- 寻找用哪种category的方法:
- 寻找用哪种category的方法:
- 寻找用哪种category的方法
- 如何在不引用头文件的情况下调用category里面的方法
- 异常处理(三)-------C++异常类
- TabLayout的简单应用
- -----hdu 4815 -01背包- Little Tiger vs. Deep Monkey
- vue使用Better-Scroll实现纵向滚动
- 权力的游戏,我是小股东,咋办?
- category 方法调用的顺序
- 如何让多个版本的Python和谐共处
- 6.10水仙花数
- SVN忽略本地文件不提交,同时不删除线上的文件
- Wind Power & Machine Learning
- 51nod 1523 非回文
- Java 实训 编写一个窗体程序模拟单词拼写
- POJ3669---跳炸弹(广搜)
- 拓扑排序(关键路径)