+ (void)load和 + (void)initialize

+ (void)load和 + (void)initialize

+ initialize+ load 是 NSObject 类的两个类方法,它们会在运行时自动调用,我们可以利用其特性做一些初始化操作。

initialize和load的区别在于:load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。

initialize初探

+ (void)initialize 消息是在该类接收到其第一个消息之前调用。

关于这里的第一个消息需要特别说明一下,对于 NSObject 的 runtime 机制而言,其在调用 NSObject 的 + (void)load 消息不被视为第一个消息,但是,如果像普通函数调用一样直接调用 NSObject 的 + (void)load 消息,则会引起 + (void)initialize 的调用。反之,如果没有向 NSObject 发送第一个消息,+ (void)initialize 则不会被自动调用。

在应用程序的生命周期中,runtime 只会向每个类发送一次 + (void)initialize 消息.

如果该类是子类,且该子类中没有实现 + (void)initialize 消息,或者子类显示调用父类实现 [super initialize], 那么则会调用其父类的实现。也就是说,父类的 + (void)initialize 可能会被调用多次。

如果类包含分类(扩展 catagory),且分类重写了initialize方法,那么则会调用分类的 initialize 实现,而原类的该方法实现不会被调用。

这个机制同 NSObject 的其他方法(除 + (void)load 方法) 一样,即如果原类同该类的分类包含有相同的方法实现,那么原类的该方法被隐藏而无法被调用。

父类的 initialize 方法先于子类的 initialize 方法调用。

实例:

@interface People : NSObject

@end

@implementation People

+ (void)initialize {
    NSLog(@"%s", __FUNCTION__);
}

@end

@interface Student : People

@end

@implementation Student

+ (void)initialize {
    NSLog(@"%s", __FUNCTION__);
}

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    Student *student = [[Student alloc] init];
}
@end

输出:

+[People initialize]
+[Student initialize]

若再次调用初始化实例,initialize 不再调用。

扩展情况下:

@interface Student (Score)

@end

@implementation Student (Score)

+ (void)initialize {
    NSLog(@"%s", __FUNCTION__);
}
@end

输出:

+[People initialize]
+[Student(Score) initialize]

load初探

+ (void)load 会在类或者类的分类添加到 Objective-c runtime 时调用,该调用发生在 application:willFinishLaunchingWithOptions: 调用之前调用。

父类的 +load 方法先于子类的 +load 方法调用,分类的 +load 方法先于类本身的 +load 方法调用。

Runtime调用+(void)load时没有autorelease pool:

原因是runtime调用+(void)load的时候,程序还没有建立其autorelease pool,所以那些会需要使用到autorelease pool的代码,都会出现异常。这一点是非常需要注意的,也就是说放在+(void)load中的对象都应该是alloc出来并且不能使用autorelease来释放。

不需要显示使用super调用父类中的方法

super的方法会成功调用,但是这是多余的,因为runtime对自动对父类的+(void)load方法进行调用,而+(void)initialize则会随子类自动激发父类的方法(如Apple文档中所言)不需要显示调用。另一方面,如果父类中的

实例:

//父类
@interface People : NSObject
@end
@implementation People

+ (void)initialize {
    NSLog(@"%@ , %s", [self class], __FUNCTION__);
}
+ (void)load {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
@end
//子类
@interface Student : People
@end
@implementation Student
+ (void)initialize {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
+ (void)load {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
@end

//子类分类
@interface Student (Score)
@end
@implementation Student (Score)
+ (void)initialize {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
+ (void)load {
    NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end

输出:

People , +[People initialize]
People, +[People load]
Student, +[Student(Score) initialize]
Student, +[Student load]
Student +[Student(Score) load]

实例二:

//父类
@interface People : NSObject
@end
@implementation People
+ (void)initialize {
    NSLog(@"%@ , %s", [self class], __FUNCTION__);
}
@end
//子类
@interface Student : People
@end
@implementation Student
+ (void)load {
    NSLog(@"%@, %s", [self class], __FUNCTION__);
}
@end

输出:

People , +[People initialize]
Student , +[People initialize]
Student, +[Student load]

当子类没有实现 +initialize 而父类有其实现时,父类的实现调用了两次,且 +initialize 的调用在 +load 调用之前,这是因为我们在 +load 实现中包含 [self class] 的调用。

总结:

+(void)load

执行时机    在程序运行后立即执行
若自身未定义,是否沿用父类的方法?   否
类别中的定义  全都执行,但后于类中的方法

+(void)initialize

执行时机    在类的方法第一次被调时执行
若自身未定义,是否沿用父类的方法?   是
类别中的定义  覆盖类中的方法,只执行一个
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容