iOS 底层分析

iOS load 和 initialize 认知

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

1. load

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我,共同进步吧!

上一篇下一篇

猜你喜欢

热点阅读