iOS load 和 initialize 認(rèn)知

最近項(xiàng)目不怎么忙,抽空看了一些博客和簡(jiǎn)書(shū)的文章,發(fā)現(xiàn)自己還是小菜雞一只,平時(shí)很基礎(chǔ)的東西認(rèn)識(shí)卻還是很淺,很淺,今天就來(lái)說(shuō)說(shuō)load 和 initialize這兩個(gè)類(lèi)方法,如果有哪些地方寫(xiě)的不對(duì)的,請(qǐng)各位大神見(jiàn)諒,并能給出指導(dǎo)性建議,感激不盡...寫(xiě)本篇文章的目的也只是想記錄一下自己的學(xué)習(xí)路程,見(jiàn)諒...

1. load

  • 什么時(shí)候調(diào)用?
    當(dāng)一個(gè)類(lèi)或者分類(lèi)添加到Objective-C RunTime中時(shí)調(diào),也就是程一已啟動(dòng)就會(huì)調(diào)用load方法,在main函數(shù)調(diào)用之前
    創(chuàng)建一個(gè)Person類(lèi)繼承自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
  • 調(diào)用的先后順序?

先加載父類(lèi)的load方法,再加載子類(lèi)的load方法,分類(lèi)的load方法在自己類(lèi)的load方法調(diào)用之后,也就是先調(diào)用本類(lèi)的,再調(diào)用分類(lèi)的load方法,還有一種就不贅述了,調(diào)用流程就是: 父類(lèi) - 子類(lèi) - 分類(lèi)

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

創(chuàng)建一個(gè)類(lèi)繼承自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]; 
}

看下面的運(yùn)行順序:先調(diào)用Person,后調(diào)用的Person的子類(lèi)


image.png
再創(chuàng)建一個(gè)類(lèi)繼承自Boy
@implementation Boy (subBoy)
+ (void)load{
    NSLog(@"%s",__func__);
}
@end

看下面的運(yùn)行順序:先調(diào)用Person - 子類(lèi) -分類(lèi)


image.png
再創(chuàng)建一個(gè)Person的分類(lèi)
#import "Person+load.h"

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

運(yùn)行結(jié)果如下:父類(lèi)-子類(lèi)-分類(lèi)


image.png
  • 調(diào)用幾次呢?

如果不是手動(dòng)去調(diào)用的話(huà),只會(huì)調(diào)用一次,在這就不演示了

2.initialize

  • 何時(shí)被調(diào)用?

通過(guò)runtime第一次向類(lèi)發(fā)送信息時(shí)調(diào)用,可以理解成懶加載吧,用到的時(shí)候才會(huì)去調(diào)用

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

  • 調(diào)用順序

父類(lèi)在子類(lèi)之前收到這個(gè)消息,如果子類(lèi)沒(méi)有實(shí)現(xiàn)initialize,runtime會(huì)調(diào)用父類(lèi)的initialize實(shí)現(xiàn),或者子類(lèi)調(diào)用[super initialize],父類(lèi)的initialize會(huì)調(diào)用多次,分類(lèi)的實(shí)現(xiàn)會(huì)覆蓋本類(lèi)的實(shí)現(xiàn)

Superclasses receive this message before their subclasses

創(chuàng)建Person類(lèi)
#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];
}

運(yùn)行發(fā)現(xiàn),分類(lèi)的initialize,覆蓋了本類(lèi)的initialize方法


image.png

驗(yàn)證 - 父類(lèi)在子類(lèi)之前收到這個(gè)消息,如果子類(lèi)沒(méi)有實(shí)現(xiàn)initialize,runtime會(huì)調(diào)用父類(lèi)的initialize實(shí)現(xiàn)

@implementation Person

+ (void)initialize
{
    NSLog(@"Person -- %s",__func__);
}
@end
創(chuàng)建Boy類(lèi)繼承自Person,沒(méi)有實(shí)現(xiàn)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

驗(yàn)證 - 分類(lèi)的initialize覆蓋本類(lèi)的initialize方法

@implementation Person (load)

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

如果你想保護(hù)自己不被多次運(yùn)行,你可以按照以下方式來(lái)構(gòu)建你的實(shí)現(xiàn):

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__);
    }
}
子類(lèi)
#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

差不多就這些內(nèi)容,如果各位有需要補(bǔ)充的可以call我,共同進(jìn)步吧!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容