OC笔记 - load | initialize
load | initialize
1 - 验证父类、原类、子类、分类中 load\initialize两方法的执行状况
2 - 代码示例:继承关系 Student\Student+Learn -> Person\Animal -> NSObject,并在每个类中重写 load\initialize两方法。目录结构如下
① load方法
// - Person.m
#import "Person.h" @implementation Person + (void)load{ NSLog(@"Person load..."); } + (void)initialize{ NSLog(@"Person initializing..."); } @end
// - Animal.m
#import "Animal.h" @implementation Animal + (void)load{ NSLog(@"Animal load..."); } + (void)initialize{ NSLog(@"Animal initializing..."); } @end
// - Student.m
#import "Student.h" @implementation Student + (void)load{ NSLog(@"Student load..."); } + (void)initialize{ NSLog(@"Student initializing..."); } @end
// - Student+Learn.m
#import "Student+Learn.h" @implementation Student (Learn) + (void)load{ NSLog(@"Student+Learn load..."); } + (void)initialize{ NSLog(@"Student+Learn initializing..."); } @end
日志信息:运行程序
当程序运行时编译器就会加载项目中所有的类(父类、本类、子类、分类...),紧接着就会调用每个类的 load方法(只调用一次)
load方法执行顺序:父类 -> 原类 -> 子类 -> 分类
一个细节问题:我们知道分类中的方法会覆盖掉原类中的方法,在 Student+Learn中已重写了 load方法,按照预想程序启动后当加载 Student时应该去执行其分类中的 load方法,但是为什么这里还会执行 Student load ?我们看下 runtime源码中的 load底层
进入 call_class_loads()我们发现它是直接从自身类的内部直接去掉用 load方法,而非采用消息传递机制
同样地不出意料的话 call_category_loads()也是直接从自身类的内部直接去掉用 load方法
② 回过头来我们看一下 initialize底层实现,它采用的是消息传递
// - ViewController.m
#import "ViewController.h" #import "Person.h" #import "Student.h" #import "Student+Learn.h" #import "Animal.h"
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{ [super touchesBegan:touches withEvent:event]; Person *p1 = [Person new]; // 注意:调用的是 Student+Learn中的初始化方法 Student *stu1 = [[Student alloc] init]; Animal *an1 = [Animal new]; }
日志信息
当一个类对象初始化时就会调用 initialize方法
initialize方法执行顺序:父类 -> 原类 -> 子类 -> 分类
③ 代码分析:试着说出以下代码会输出什么
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{ [super touchesBegan:touches withEvent:event]; [Person load]; [Student load]; }
当点击视图时 [Person load]首先会触发初始化方法 Person initializing,然后去执行 Person load
而 [Student load]会先触发 Student+Learn initializing,然后去执行 Student+Learn load。注:Student触发的 load方法是分类中的 load方法,这不同于程序加载时的 load机制
除第一次点击外,以后的每次点击只会触发 load方法,因为 initialize方法只会执行一次