导语:iOS开发中经常会看到在自定义类中重写load、initialize两个类方法,之前对这两个方法理解比较浅,今天来深入探讨下两个方法的实际作用
load方法
- 程序启动的时候,会将所有类加载到代码区。
- load方法会在当前类被加到内存的时候调用,整个过程只会调用一次。
- 如果类存在继承关系,则会先调用父类的load方法,然后调用子类的load方法。
- 如果类的分类也实现了load方法,会先调用类的load方法,而后调用分类的load方法
- 当子类没有实现load方法,不会调用父类的loaf方法
2021-10-29 09:13:42.465207+0800 类的本质[2693:59888] +[Person load]
2021-10-29 09:13:42.466004+0800 类的本质[2693:59888] +[Man load]
2021-10-29 09:13:42.466063+0800 类的本质[2693:59888] +[GentleMan load]
2021-10-29 09:13:42.466197+0800 类的本质[2693:59888] +[Person(Work) load]
2021-10-29 09:13:42.466235+0800 类的本质[2693:59888] +[Man(Work) load]
2021-10-29 09:13:42.466269+0800 类的本质[2693:59888] +[GentleMan(Work) load]
上面的类的继承关系Person > Man > GentleMan,所以依次调用Person、Man、GentleMan的load方法,分类的load方法会在类的load方法调用完之后调用,调用的顺序由编译的顺序决定。
2021-10-29 09:13:42.466197+0800 类的本质[2693:59888] +[Person(Work) load]
2021-10-29 09:13:42.466235+0800 类的本质[2693:59888] +[Man(Work) load]
2021-10-29 09:13:42.466269+0800 类的本质[2693:59888] +[GentleMan(Work) load]
2021-10-29 09:21:59.535424+0800 类的本质[2929:67061] +[GentleMan(Work) load]
2021-10-29 09:21:59.535470+0800 类的本质[2929:67061] +[Person(Work) load]
2021-10-29 09:21:59.535510+0800 类的本质[2929:67061] +[Man(Work) load]
initialize方法
- initialize方法会在类第一次使用的时候调用。
- initialize方法是阻塞安全的,所以initialize方法中应该做一些简单的初始化操作
- 如果子类也实现了initialize方法,会跟load方法调用的顺序一样,先调用父类的initialize方法,之后调用子类的initialize方法
- 如果子类没有实现initialize,会调用父类的initialize方法(所以父类的initialize有可能调用多次,可以理解为子类没有实现initialize方法时,会拷贝一份父类的initialize方法,而后在依次调用)
- 如果分类重写了initialize方法,会覆盖类本身的initialize方法
- 由于是系统自动调用,也不需要再调用 [super initialize],否则父类的initialize会被多次执行。子类会从继承关系依次调用
- 当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)
2021-10-29 09:38:40.921775+0800 类的本质[3416:81482] +[Person initialize]
2021-10-29 09:38:40.922198+0800 类的本质[3416:81482] +[Man initialize]
2021-10-29 09:38:40.922246+0800 类的本质[3416:81482] +[GentleMan initialize]
GentleMan没有实现initialize方法的时候
2021-10-29 09:40:18.681950+0800 类的本质[3463:82974] +[Person initialize]
2021-10-29 09:40:18.682322+0800 类的本质[3463:82974] +[Man initialize]
2021-10-29 09:40:18.682369+0800 类的本质[3463:82974] +[Man initialize]
Person分类实现了initialize方法
2021-10-29 09:41:14.920573+0800 类的本质[3491:83855] +[Person(Work) initialize]
2021-10-29 09:41:14.920945+0800 类的本质[3491:83855] +[Man initialize]
2021-10-29 09:41:14.920999+0800 类的本质[3491:83855] +[Man initialize]
总结
1、initialize只会调用一次,分类会覆盖本身的initialize方法,所以如果需要类和分类分别独立初始化,使用load方法更好
2、initialize方法中不应该执行太复杂的初始化过程,而应将其限制为简单的类本地初始化
3、当子类没有实现initialize方法时候,防止父类的initialize方法多次调用
4、官方解释
//In Person.m
+(void)initialize
{
if(self == [Person class])
{
NSLog(@"%s",__FUNCTION__);
}
}