load和initialize

load和initialize的执行过程经常被问到在这里简单梳理一番

load方法

分别创建类Person和Car并实现load方法

#import "Person.h"

@implementation Person

+(void)load{
    NSLog(@"%s %@",__FUNCTION__,[self class]);
}

@end

#import "Car.h"

@implementation Car

+(void)load{
    NSLog(@"%s %@",__FUNCTION__,[self class]);
}

@end

执行结果

img01
img02

验证了load方法执行顺序就是编译顺序
这时候没有用到这两个类,在Compile Sources中删除之,看看运行结果


img03
img04

可以运行成功但是load方法都没有执行,这是因为我们现在没有用到这个Class

img05

即使在ViewController中引入Person.h头文件也没有问题,这是因为OC是一门动态语言在编译时不检查方法是否实现

用到Person类时就会报错了

//运行报错,Compile Sources中添加类Person和Car问题解决
[Person class];

这个时候了解了load方法是在编译时执行的,load执行顺序就是Compile Sources列表中的顺序,一个类只会被编译一次,所以一个类的load方法也只会执行一次

子类load方法

创建子类Student

#import "Person.h"

NS_ASSUME_NONNULL_BEGIN

@interface Student : Person

@end

NS_ASSUME_NONNULL_END
#import "Student.h"

@implementation Student
+(void)load{
    NSLog(@"%s %@",__FUNCTION__,[self class]);
}
@end

运行结果

img06
img07

这时先执行父类load再执行子类load,跟Compile Sources中顺序就没有关系了,手动删除子类Student或者父类Person也都没有问题,可以正常运行。

Category中的load方法

创建Person类的Category,Person+Study

#import "Person.h"

NS_ASSUME_NONNULL_BEGIN

@interface Person (Study)

@end

NS_ASSUME_NONNULL_END
#import "Person+Study.h"

@implementation Person (Study)

+ (void)load{
    NSLog(@"%s %@",__FUNCTION__,[self class]);
}

@end

执行结果

img09

这个时候执行结果先执行父类load再执行子类load,最后执行分类Category中的load方法,顺序跟Compile Sources中顺序无关,在用不到分类是从Compile Sources列表中删除也可以正常运行,但是如果有多个分类的话就按照Compile Sources中的顺序执行分类中的load方法了

initialize方法

如果父类Person和子类Student以及分类Person+Study都实现了initialize方法

#import "Person.h"

@implementation Person


+ (void)initialize
{
    NSLog(@"Person类%s %@",__FUNCTION__,[self class]);
}

@end
#import "Student.h"

@implementation Student

+ (void)initialize
{
    NSLog(@"Student类%s %@",__FUNCTION__,[self class]);
}

@end
#import "Person+Study.h"

@implementation Person (Study)

+ (void)initialize{
    NSLog(@"分类 %s %@",__FUNCTION__,[self class]);
}

@end

当给Class发送第一条消息时

#import "ViewController.h"
#import "Person.h"
#import "Student.h"
#import "Person+Study.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [Student alloc];
   
    // Do any additional setup after loading the view.
}


@end

可以看到执行结果

 分类 +[Person(Study) initialize] Person
 Student类+[Student initialize] Student

先执行了分类中的initialize再执行子类的initialize,难道分类会覆盖Person类中的initialize??先删除分类看看结果

 Person类+[Person initialize] Person
 Student类+[Student initialize] Student

果然分类会覆盖Person类中的initialize,再将Person类中的initialize注释掉执行以下

Student类+[Student initialize] Student

只执行了子类的initialize方法,如果父类实现了initialize方法但是子类没有实现了

 Person类+[Person initialize] Person
 Person类+[Person initialize] Student

发现调用了两次父类中的initialize方法,通过类型判断可以区分父类还是子类以及是哪一个字类

小结:

  • 分类中的initialize会覆盖initialize
  • 先调用字类中的initialize再调用父类的initialize
  • 子类实现了initialize父类没实现那么创建子类对象只调用一次
  • 子类没有实现initialize但是父类实现了initialize,那么创建子类时调用两次父类的initialize,通过类型判断可加以区分

参考文章
iOS-init与initialize
iOS类方法load和initialize详解

你可能感兴趣的:(load和initialize)