美文网首页iOS 底层分析
iOS load 和 initialize 认知

iOS load 和 initialize 认知

作者: 郭小弟 | 来源:发表于2017-12-20 16:45 被阅读11次
    最近项目不怎么忙,抽空看了一些博客和简书的文章,发现自己还是小菜鸡一只,平时很基础的东西认识却还是很浅,很浅,今天就来说说load 和 initialize这两个类方法,如果有哪些地方写的不对的,请各位大神见谅,并能给出指导性建议,感激不尽...写本篇文章的目的也只是想记录一下自己的学习路程,见谅...

    1. load

    • 什么时候调用?
      当一个类或者分类添加到Objective-C RunTime中时调,也就是程一已启动就会调用load方法,在main函数调用之前
      创建一个Person类继承自NSObject
    int main(int argc, char * argv[]) {
        @autoreleasepool {
            NSLog(@"%s",__func__);
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }
    #import "Person.h"
    
    @implementation Person
    
    + (void)load
    {
        NSLog(@"Person -- %s",__func__);
    }
    @end
    
    在控制器
    - (void)viewDidLoad {
        [super viewDidLoad];
        Person *p = [Person new]; 
    }
    
    image.png
    • 调用的先后顺序?

    先加载父类的load方法,再加载子类的load方法,分类的load方法在自己类的load方法调用之后,也就是先调用本类的,再调用分类的load方法,还有一种就不赘述了,调用流程就是: 父类 - 子类 - 分类

    官方文档
    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

    创建一个类继承自Person
    
    Boy.m文件
    @implementation Boy
    + (void)load
    {
        NSLog(@"--%s",__func__);
    }
    @end
    
    Person.m文件
    @implementation Person
    
    + (void)load
    {
        NSLog(@"Person -- %s",__func__);
    }
    @end
    
    ViewController.m
    - (void)viewDidLoad {
        [super viewDidLoad];
        Person *p = [Person new]; 
    }
    

    看下面的运行顺序:先调用Person,后调用的Person的子类


    image.png
    再创建一个类继承自Boy
    @implementation Boy (subBoy)
    + (void)load{
        NSLog(@"%s",__func__);
    }
    @end
    

    看下面的运行顺序:先调用Person - 子类 -分类


    image.png
    再创建一个Person的分类
    #import "Person+load.h"
    
    @implementation Person (load)
    + (void)load
    {
        NSLog(@"%s",__func__);
    }
    @end
    

    运行结果如下:父类-子类-分类


    image.png
    • 调用几次呢?

    如果不是手动去调用的话,只会调用一次,在这就不演示了

    2.initialize

    • 何时被调用?

    通过runtime第一次向类发送信息时调用,可以理解成懒加载吧,用到的时候才会去调用

    The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program

    • 调用顺序

    父类在子类之前收到这个消息,如果子类没有实现initialize,runtime会调用父类的initialize实现,或者子类调用[super initialize],父类的initialize会调用多次,分类的实现会覆盖本类的实现

    Superclasses receive this message before their subclasses

    创建Person类
    #import "Person.h"
    @implementation Person
    + (void)initialize
    {
        NSLog(@"Person -- %s",__func__);
    }
    @end
    #import "Person+load.h"
    
    @implementation Person (load)
    
    + (void)initialize
    {
        NSLog(@"%s",__func__);
    }
    @end
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        Person *p = [Person new];
    }
    

    运行发现,分类的initialize,覆盖了本类的initialize方法


    image.png

    验证 - 父类在子类之前收到这个消息,如果子类没有实现initialize,runtime会调用父类的initialize实现

    @implementation Person
    
    + (void)initialize
    {
        NSLog(@"Person -- %s",__func__);
    }
    @end
    创建Boy类继承自Person,没有实现initialize
    @implementation Boy
    @end
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        Boy *boy = [Boy new];
    }
    
    image.png

    验证 - 分类的initialize覆盖本类的initialize方法

    @implementation Person (load)
    
    + (void)initialize
    {
        NSLog(@"%s",__func__);
    }
    @end
    
    image.png

    如果你想保护自己不被多次运行,你可以按照以下方式来构建你的实现:

    If you want to protect yourself from being run multiple times, you can structure your implementation along these lines:
    Listing 1

    + (void)initialize {
        if (self == [Person self]) {
        
            NSLog(@"%s",__func__);
        }
    }
    子类
    #import "Boy.h"
    
    @implementation Boy
    
    + (void)initialize
    {
        [super initialize];
        NSLog(@"%s",__func__);
    }
    @end
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        Boy *boy = [Boy new];
    }
    
    image.png

    如果改一下

    #import "Person.h"
    
    @implementation Person
    
    + (void)initialize {
    //    if (self == [Person self]) {
        
            NSLog(@"%s",__func__);
    //    }
    }
    @end
    
    image.png

    差不多就这些内容,如果各位有需要补充的可以call我,共同进步吧!

    相关文章

      网友评论

        本文标题:iOS load 和 initialize 认知

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