OC进阶 - load | initialize
load | initialize
1 - 验证父类、当前类、子类、分类中 load/initialize 两方法的执行状况。继承关系如是 Student -> 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 方法,按照预想当程序启动后应该只会执行分类中的 load 方法,但为什么当前类 Student 和它的分类 Student+Learn 均执行了 load 方法 ?
接下来我们打开 Runtime 源码
打开 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<UITouch *> *)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 方法执行顺序:父类 -> 当前类 -> 子类 -> 分类
③ 代码分析:试着说出以下代码会输出什么(Person、Student 均是首次使用)
- (void)touchesBegan:(NSSet<UITouch *> *)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 方法
以后的每次点击只会触发手动调用的 load 方法,因为 initialize 方法只会执行一次
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)