新建一个Person类,然后对Person添加三个分类Person+Category1、Person+Category2和Person+Category3,Category1和Category2中实现load方法,Category3什么也不做,添加Student和Teacher类继承自Person,Student实现load方法,Teacher什么也不做
Person
.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject
@end
NS_ASSUME_NONNULL_END
.m
@implementation Person
+ (void)load {
NSLog(@"%s", __func__);
}
@end
Person+Category1
.h
#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
@interface Person (Category1)
@end
NS_ASSUME_NONNULL_END
.m
@implementation Person (Category1)
+ (void)load {
NSLog(@"%s", __func__);
}
@end
Person+Category2
.h
#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
@interface Person (Category2)
@end
NS_ASSUME_NONNULL_END
.m
@implementation Person (Category2)
+ (void)load {
NSLog(@"%s", __func__);
}
@end
Person+Category3
.h
#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
@interface Person (Category3)
@end
NS_ASSUME_NONNULL_END
.m
@implementation Person (Category3)
@end
Student
.h
#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
@interface Student : Person
@end
NS_ASSUME_NONNULL_END
.m
@implementation Student
+ (void)load {
NSLog(@"%s", __func__);
}
@end
Teacher
.h
#import "Person.h"
NS_ASSUME_NONNULL_BEGIN
@interface Teacher : Person
@end
NS_ASSUME_NONNULL_END
.m
#import "Teacher.h"
@implementation Teacher
@end
查看Build Phases中Compile Sources顺序:
运行项目,打印结果:
[Person.m:20行] +[Person load]
[Student.m:21行] +[Student load]
[Person+Category2.m:21行] +[Person(Category2) load]
[Person+Category1.m:21行] +[Person(Category1) load]
[main.m:25行] main
交换Compile Sources中Person+Category1.m和Person+Category2.m的编译顺序
运行项目,打印结果:
[Person.m:20行] +[Person load]
[Student.m:21行] +[Student load]
[Person+Category1.m:21行] +[Person(Category1) load]
[Person+Category2.m:21行] +[Person(Category2) load]
[main.m:25行] main
从打印结果可知:
- load方法在main函数执行之前调用
- 先调用父类的load方法,无关编译顺序
- 同一个类的分类,先编译的分类先调用它的load方法
- 分类load方法不会覆盖本类的load方法
- 当子类未实现load方法时,加载该类时,不会去调用其父类的load方法
一、为Person、Student和Teacher类添加init和initialize方法
@implementation Person
+ (void)load {
NSLog(@"%s", __func__);
}
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"%s", __func__);
}
return self;
}
+ (void)initialize
{
if (self == [self class]) {
NSLog(@"%s", __func__);
}
}
@end
- 在控制器中仅创建Person的实例:
Person *person1 = [[Person alloc] init];
运行项目,打印结果:
[Person.m:35行] +[Person initialize]
[Person.m:27行] -[Person init]
- 在控制器中仅创建Student的实例:
Student *student1 = [[Student alloc] init];
运行项目,打印结果:
[Person.m:35行] +[Person initialize]
[Student.m:37行] +[Student initialize]
[Person.m:27行] -[Person init]
[Student.m:29行] -[Student init]
- 将子类Student的initialize方法实现去掉,仍仅创建Student的实例,运行打印结果:
[Person.m:35行] +[Person initialize]
[Person.m:35行] +[Person initialize]
[Person.m:27行] -[Person init]
[Student.m:29行] -[Student init]
二、为Person+Category1和Person+Category2也添加init和initialize实现
- 在控制器仅创建Person实例,运行结果:
[Person+Category1.m:36行] +[Person(Category1) initialize]
[Person+Category1.m:28行] -[Person(Category1) init]
- 仅创建Student实例
[Person+Category1.m:36行] +[Person(Category1) initialize]
[Student.m:37行] +[Student initialize]
[Person+Category1.m:28行] -[Person(Category1) init]
[Student.m:29行] -[Student init]
- initialize和init方法在main函数之后调用,load方法在main函数之前调用
- initialize在类或者其子类的第一次初始化之前调用
- 父类的initialize方法比子类先执行
- 当子类的initialize方法未实现时,会调用父类initialize方法
- 子类实现initialize方法时,不会覆盖父类initialize方法
- 当有多个category都实现了initialize方法时,会覆盖类中的方法,并且只执行一个(会执行Compile Sources中最后一个Category的initialize方法)
- 只是把类文件引用进项目,没有使用,其initialize不会被调用(Teacher类没有使用,其initialize方法没有调用)
参考:
iOS+load和+initialize详解
oc中 load,initialize,init方法对比总结
iOS load方法与initialize方法
ios load方法调用顺序