美文网首页
iOS中load和initialize方法总结

iOS中load和initialize方法总结

作者: 繁星mind | 来源:发表于2019-05-14 19:19 被阅读0次

本文demo在这里LoadAndInitializeDemo

Load方法执行时机和执行顺序

load方法是在main函数前调用的,引入项目中就会调用,且只会调用一次,那么当类和类的Category都有load方法是怎么调用的?类有多个Category,且都实现了load方法又是怎么调用的?子类和父类都实现了load方法是怎么调用的?带着这些问题,我们来看下下面的结论和测试用例。

测试用例:

**类关系:**
==========================

人类:XMPeople
XMPeople:NSObject
XMPeople (Category1)
XMPeople (Category2)

人类子类:XMMan
XMMan:XMPeople
XMMan (Category1)
XMMan (Category2)

人类子类:XMWoman
XMWoman:XMPeople

==========================

动物类:XMWoman
XMAnimal : NSObject

==========================

#pragma ==========================
#pragma 人类:XMPeople
#pragma ==========================
@implementation XMPeople

+ (void)load
{
    NSLog(@"%@==========%@", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMPeople (Category1)

+ (void)load
{
    NSLog(@"%@==========%@Category1", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMPeople (Category2)

+ (void)load
{
    NSLog(@"%@==========%@Category2", NSStringFromSelector(_cmd), [self class]);
}

@end

#pragma ==========================
#pragma 人类子类:XMMan
#pragma ==========================

@implementation XMMan

+ (void)load
{
    NSLog(@"%@==========%@", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMMan (Category1)

+ (void)load
{
    NSLog(@"%@==========%@Category1", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMMan (Category2)

+ (void)load
{
    NSLog(@"%@==========%@Category2", NSStringFromSelector(_cmd), [self class]);
}

@end
#pragma ==========================
#pragma 人类子类:XMWoman
#pragma ==========================
@implementation XMWoman

@end

#pragma ==========================
#pragma 动物类:XMAnimal
#pragma ==========================
@implementation XMAnimal

+ (void)load
{
    NSLog(@"%@==========%@", NSStringFromSelector(_cmd), [self class]);
}

@end

类文件编译顺序:

Bilid Phases中文件顺序.png

输出结果:

2019-05-14 17:09:53.867210+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMAnimal
2019-05-14 17:09:53.867725+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMPeople
2019-05-14 17:09:53.867813+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMMan
2019-05-14 17:09:53.867913+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMManCategory2
2019-05-14 17:09:53.867979+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMPeopleCategory1
2019-05-14 17:09:53.868071+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMManCategory1
2019-05-14 17:09:53.868179+0800 LoadAndInitalizeDemo[9511:2236726] load==========XMPeopleCategory2

结论:

1.当类和类Category中load方法都存在时,先调用类中load方法,Category中load方法后调用(注意:Category中load晚于所有的类中load方法调用)

2.父类load方法优先于子类load方法(参考人类子类:XMMan和人类:XMPeople)

3.子类没实现load方法,不会调用父类load方法(参考人类子类:XMWoman)

4.Category的load调用顺序,与对应类之间的关系无关,与编译顺序一致(参考XMPeople (Category1)、XMPeople (Category2)、 XMMan (Category1)、XMMan (Category2) )

5.类与类的Category中的load方法都会调用

6.当有多个类时,load调用顺序和类文件编译顺序有关(参考动物类:XMAnimal和人类:XMPeople)


Initialize方法执行顺序

Initialize方法是在类第一次初始化的时候调用的,且只调用一次,但是在子类和父类都是有Initialize方法的时候,是怎么调用的呢?类和Category中都有Initialize又是怎么调用的? 子类没有实现Initialize方法,会不会调用父类的Initialize方法呢?带着这些问题,我们可以看下下面的结论和测试实验。

测试用例:

#pragma ==========================
#pragma 人类:XMPeople
#pragma ==========================
@implementation XMPeople

+ (void)initialize
{
    NSLog(@"%@==========%@", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMPeople (Category1)

+ (void)initialize
{
    NSLog(@"%@==========%@Category1", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMPeople (Category2)

+ (void)initialize
{
    NSLog(@"%@==========%@Category2", NSStringFromSelector(_cmd), [self class]);
}

@end

#pragma ==========================
#pragma 人类子类:XMMan
#pragma ==========================

@implementation XMMan

+ (void)initialize
{
    NSLog(@"%@==========%@", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMMan (Category1)

+ (void)initialize
{
    NSLog(@"%@==========%@Category1", NSStringFromSelector(_cmd), [self class]);
}

@end

@implementation XMMan (Category2)

+ (void)initialize
{
    NSLog(@"%@==========%@Category2", NSStringFromSelector(_cmd), [self class]);
}

@end
#pragma ==========================
#pragma 人类子类:XMWoman
#pragma ==========================
@implementation XMWoman

@end

类文件编译顺序:

Bilid Phases中文件顺序.png

实例对象创建顺序和输出记过:

测试1:
XMPeople *people = [XMPeople new];

结果1:
2019-05-14 18:11:46.710885+0800 LoadAndInitalizeDemo[25371:2328024] initialize==========XMPeopleCategory2

**************************************************************************************

测试2:
XMMan *man = [XMMan new];

结果2:
2019-05-14 17:41:23.177725+0800 LoadAndInitalizeDemo[18632:2284715] initialize==========XMPeopleCategory2
2019-05-14 17:41:23.177871+0800 LoadAndInitalizeDemo[18632:2284715] initialize==========XMManCategory1

**************************************************************************************
测试3:
XMMan *man = [XMMan new];
XMPeople *people = [XMPeople new];

结果3:
2019-05-14 18:10:16.282968+0800 LoadAndInitalizeDemo[25059:2325808] initialize==========XMPeopleCategory2
2019-05-14 18:10:16.283091+0800 LoadAndInitalizeDemo[25059:2325808] initialize==========XMManCategory1

**************************************************************************************

测试4:
XMWoman *woman = [XMWoman new];

结果4:
2019-05-14 17:56:06.076544+0800 LoadAndInitalizeDemo[22157:2306915] initialize==========XMPeopleCategory2
2019-05-14 17:56:06.076775+0800 LoadAndInitalizeDemo[22157:2306915] initialize==========XMWomanCategory2

结论:


1.如果类和类Category都实现了initialize方法,调用Category的initialize方法,会覆盖类中的方法,只执行一个,如果多个category,则调用编译顺序最后的initialize方法。(测试1)

2.如果父类和子类都实现了initialize方法,在调用子类时,如果父类的initialize方法调用过,则只调用子类initialize方法,如果父类没用过,则先调用父类的Category的initialize方法,在调用子类的initialize方法(测试2)。如果调用子类的时候,已经初始化过父类的initialize,则在初始化父类的时候,不会再调用initialize方法(测试3)

3.如果子类没有实现initialize方法,父类实现了initialize方法,调用子类的时候,会先调用父类的initialize方法,再调用子类的实例方法。(测试4)

总结:

Load执行顺序总结

1.当类和类Category中load方法都存在时,先调用类中load方法,Category中load方法后调用(注意:Category中load晚于所有的类中load方法调用)

2.父类load方法优先于子类load方法(参考人类子类:XMMan和人类:XMPeople)

3.子类没实现load方法,不会调用父类load方法(参考人类子类:XMWoman)

4.Category的load调用顺序,与对应类之间的关系无关,与编译顺序一致(参考XMPeople (Category1)、XMPeople (Category2)、 XMMan (Category1)、XMMan (Category2) )

5.类与类的Category中的load方法都会调用

6.当有多个类时,load调用顺序和类文件编译顺序有关(参考动物类:XMAnimal和人类:XMPeople)

initialize执行顺序总结

1.如果类和类Category都实现了initialize方法,调用Category的initialize方法,会覆盖类中的方法,只执行一个,如果多个category,则调用编译顺序最后的initialize方法。(测试1)

2.如果父类和子类都实现了initialize方法,在调用子类时,如果父类的initialize方法调用过,则只调用子类initialize方法,如果父类没用过,则先调用父类的Category的initialize方法,在调用子类的initialize方法(测试2)。如果调用子类的时候,已经初始化过父类的initialize,则在初始化父类的时候,不会再调用initialize方法(测试3)

3.如果子类没有实现initialize方法,父类实现了initialize方法,调用子类的时候,会先调用父类的initialize方法,再调用子类的实例方法。(测试4)

参考:
Objective-C 深入理解 +load 和 +initialize
iOS类方法load和initialize详解

相关文章

网友评论

      本文标题:iOS中load和initialize方法总结

      本文链接:https://www.haomeiwen.com/subject/ktkeaqtx.html