美文网首页原理iOS 好文基础
一道题搞清楚Objective-C中load和initializ

一道题搞清楚Objective-C中load和initializ

作者: SuperMario_Nil | 来源:发表于2017-02-26 01:18 被阅读977次

Objective-C中有两个方法比较特殊,他们会在Runtime时根据情况自动调用,下面我们简单分析一下调用时机以及使用场景~

一般在iOS初中级面试时偶尔会被问到load和initialize方法,我出了一道题,估计会搞晕很多人。大家来看一下下面的程序以及图一会输出什么?(这个Demo请点击这里查看详情)

//Father.m 
+ (void)load {
    NSLog(@"Father:%s %@", __FUNCTION__, [self class]);
}
+ (void)initialize {
    NSLog(@"Father:%s %@", __FUNCTION__, [self class]);
}
//Son.m   Class Son Extends Father
+ (void)load {
    NSLog(@"Son:%s %@", __FUNCTION__, [self class]);
}
//Son+load.m
+ (void)load {
    NSLog(@"Son+load:%s %@", __FUNCTION__, [self class]);
}
//Other.m 
+ (void)load {
    NSLog(@"Other:%s %@", __FUNCTION__, [self class]);
}
+ (void)initialize {
    NSLog(@"Other:%s %@", __FUNCTION__, [self class]);
}
//Other+initialize.m
+ (void)initialize {
    NSLog(@"Other+initialize:%s %@", __FUNCTION__, [self class]);
}
//main.m
int main(int argc, char * argv[]) {
        NSLog(@"Main method start!");
        return 0;
}
我是图一

答案是:


首先来说一下调用时机:

  • +load()方法:官方文档上说Invoked whenever a class or category is added to the Objective-C runtime;,意思是说当类被加载到runtime的时候就会运行,也就是说是在main.m之前~会根据Compile Sources中的顺序来加载,但还有一个需注意的加载顺序
  • A class’s +load method is called after all of its superclasses’ +load methods.
  • A category +load method is called after the class’s own +load method.
    意思是说有继承关系的会先调用父类+load,扩展的类在所有的类在方法之后再开始扩展方法的+load,每个类只会调用一次+load
  • +initialize()方法:官方文档上说Initializes the class before it receives its first message.意思是在类接收第一条消息之前初始化类
    值得注意的点是:类初始化的时候每个类只会调用一次+initialize(),如果子类没有实现+initialize(),那么将会调用父类的+initialize(),也就是意味着父类的+initialize()可能会被多次调用

最后说下使用场景:

  • +load():通常用来进行Method Swizzle,尽量避免过于复杂以及不必要的代码
  • +initialize():一般用于初始化全局变量或静态变量

EOF:

好了,通过上述的所概括应该能知道为什么答案是那样了另外如果文章中有什么错误或者意见请大家多多指教

相关文章

网友评论

  • Mars飘殇:我自己做了个测试,结论是:父类、子类和子类分类的load方法调用顺序是:父类、子类、子类分类,这三者和编译顺序无关;另外initialize方法打印顺序是:父类、子类分类、子类,也就是说只有父类和子类分类不实现initialize方法时,若子类实现了则会打印子类的initialize方法。另外在做测试时候任意注释了initialize或者load方法都需要Shift+Command+K对项目进行clean后才能运行正常
    SuperMario_Nil:不需要Clean吧?什么情况需要clean?
  • helloDolin:这个作为面试题的话,我估计已经入坑了,load方法里竟然发送消息 [self class]
    我就在想main方法里,哪里有发消息,initialize不会调用的,只会走load方法,哎

    "+initialize()方法:官方文档上说Initializes the class before it receives its first message.意思是会在类收到第一个消息前调用初始化~"
    感觉翻译成:在接收第一条消息之前初始化类 更好
    SuperMario_Nil:感谢,已改正~我表达的还是太口语化
    我只想用尽量简单的代码把+initialize 和+load知识点都覆盖到,不会有公司出这么变态的笔试题的
  • 萧城x:A class’s +load method is called after all of its superclasses’ +load methods.
    A category +load method is called after the class’s own +load method.


    这两句话 好像在这里 没有体现 这里 是根据compile source 顺序来加载的
  • 暗夜血狐:我觉得你这个题目容易让人有点不大明白 NSLog里面调用 [self class] 导致类方法被调用 然后造成initialize在的log顺序在load的log前面了
    SuperMario_Nil:我只想用尽量简单的代码把+initialize 和+load知识点都覆盖到,一般不会有这么变态的笔试题的
  • 啊哈呵:"值得注意的点是:类初始化的时候每个类只会调用一次+initialize()"
    我觉得是:不要说类初始化,而是类第一个方法调用时(随便一个xxx方法),先执行+initialize(),然后在执行xxx方法。
    另外:本身的+initialize() 会被category的覆盖,
    SuperMario_Nil:感谢,之前的表达有问题,已经改正~
    category覆盖的这个所有方法都会的,包括+initialize(),就没写

本文标题:一道题搞清楚Objective-C中load和initializ

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