OC笔记 - load | initialize


load | initialize

1 - 验证父类、原类、子类、分类中 load\initialize两方法的执行状况

2 - 代码示例:继承关系 Student\Student+Learn -> Person\Animal -> NSObject,并在每个类中重写 load\initialize两方法。目录结构如下

① load方法

// - Person.m

#import "Person.h"
@implementation Person

+ (void)load{
    
    NSLog(@"Person load...");
}

+ (void)initialize{
    
    NSLog(@"Person initializing...");
}

@end

// - Animal.m

#import "Animal.h"
@implementation Animal

+ (void)load{
    
    NSLog(@"Animal load...");
}

+ (void)initialize{

    NSLog(@"Animal initializing...");
}

@end

// - Student.m

#import "Student.h"
@implementation Student
+ (void)load{
    
    NSLog(@"Student load...");
}


+ (void)initialize{
    
    NSLog(@"Student initializing...");
}

@end

// - Student+Learn.m

#import "Student+Learn.h"
@implementation Student (Learn)

+ (void)load{
    
    NSLog(@"Student+Learn load...");
}


+ (void)initialize{
    
    NSLog(@"Student+Learn initializing...");
}

@end

日志信息:运行程序

程序运行时编译器就会加载项目中所有的类(父类、本类、子类、分类...),紧接着就会调用每个类的 load方法(只调用一次)

load方法执行顺序:父类 -> 原类 -> 子类 -> 分类

一个细节问题:我们知道分类中的方法会覆盖掉原类中的方法,在 Student+Learn中已重写了 load方法,按照预想程序启动后当加载 Student时应该去执行其分类中的 load方法,但是为什么这里还会执行 Student load ?我们看下 runtime源码中的 load底层

进入 call_class_loads()我们发现它是直接从自身类的内部直接去掉用 load方法,而非采用消息传递机制

同样地不出意料的话 call_category_loads()也是直接从自身类的内部直接去掉用 load方法

② 回过头来我们看一下 initialize底层实现,它采用的是消息传递

// - ViewController.m

#import "ViewController.h"
#import "Person.h"
#import "Student.h"
#import "Student+Learn.h"
#import "Animal.h"
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    
    Person *p1 = [Person new];
    // 注意:调用的是 Student+Learn中的初始化方法
    Student *stu1 = [[Student alloc] init];
    Animal *an1 = [Animal new];
}

日志信息

当一个类对象初始化时就会调用 initialize方法

initialize方法执行顺序:父类 -> 原类 -> 子类 -> 分类

③ 代码分析:试着说出以下代码会输出什么

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    [Person load];
    [Student load];

}

当点击视图时 [Person load]首先会触发初始化方法 Person initializing,然后去执行 Person load

而 [Student load]会先触发 Student+Learn initializing,然后去执行 Student+Learn load。注:Student触发的 load方法是分类中的 load方法,这不同于程序加载时的 load机制

除第一次点击外,以后的每次点击只会触发 load方法,因为 initialize方法只会执行一次