那么原方法失效,分类方法生效的原理是?想弄清这点先来看一下类的初始化,首先oc是动态语言,建立在runtime 的基础上,同样类的初始化也是动态的,根类NSObject 的+load和+initilize两个方法,用于类的初始化,我们这里要着重看的是+load方法:+load方法是当类或分类被添加到 Objective-C runtime 时被调用的,实现这个方法可以让我们在类加载的时候执行一些类相关的行为。子类的+load方法会在它的所有父类的+load方法执行之后执行,而分类的+load方法会在它的主类的+load方法执行之后执行。但是不同的类之间的+load方法的调用顺序是不确定的。原因就在这里,因为加载顺序是父类先+load,然后子类+load,然后分类+load,那么如果分类重写子类方法:首先子类+load,将方法添加到类的方法列表methodLists,然后分类+load,将重写的方法添加到方法列表中,但是这里存在几点疑问:1. 方法列表methodLists里是否会有两个SEL相同的方法?2. 如果会有,这两个方法在方法列表中的顺序是怎样的?(顺序决定哪个被调用)下面来求证一下:```#import "TestCategory.h"/主类实现/@implementation TestCategory- (void)newMethod { NSLog(@"主类");}@end#import "TestCategory+add.h"/分类一实现/@implementation TestCategory (add)- (void)newMethod { NSLog(@"分类一");}@end#import#import "TestCategory.h"@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; id LenderClass = objc_getClass("TestCategory"); unsigned int outCount, i; //获取实例方法列表 Method *methodList = class_copyMethodList(LenderClass, &outCount); for (i=0; iCompile Sources里面的顺序从上至下编译的,那么很明显就像子类和分类一样,后编译的后load,即后添加到方法列表,所以后编译的分类,方法会放到方法列表顶部,调用的时候先执行。
添加代码验证一下:
#import "TestCategory+addAgain.h"
/*分类二实现*/
@implementation TestCategory (addAgain)
- (void)newMethod {
NSLog(@"分类二");
}
@end
看输出
2017-07-19 22:18:13.593 TestRuntimeProperty[28385:1331972] instanceMethod:newMethod
2017-07-19 22:18:13.593 TestRuntimeProperty[28385:1331972] instanceMethod:newMethod
2017-07-19 21:18:13.593 TestRuntimeProperty[28385:1331972] instanceMethod:newMethod
2017-07-19 22:18:13.594 TestRuntimeProperty[28385:1331972] 分类一
结果输出仍然是分类一,那就说明"TestCategory+add.h"在buildPhases->Compile Sources里面的顺序是靠下的,看下buildPhases的确如此
网友评论