类与分类的搭配分析

167 阅读4分钟

类的加载

类是什么时候开始加载?我们可以从load这个方法入手,类里面如果实现load方法的话,则该类在编译时就开始加载,为非懒加载类; 如果没有实现load方法的话,则是在调用的时候进行加载例如时间[Objc alloc]的时候

类在系统中的加载顺序

我们根据代码验证

第一步创建YDPerson这个类,进行初始化和load方法实现
#import "YDPerson.h"
@implementation YDPerson
-(instancetype)init{
self = [super init];
if (self) {
NSLog(@"类的初始化 %s",__func__);
}
return self;
}
+(void)load{
NSLog(@"load %s",__func__);

}

@end

第二步,main.m里面进行打印,验证其打印顺序
#import <Foundation/Foundation.h>
#import "YDPerson.h"
int main(int argc, const char * argv[]) {
@autoreleasepool{
NSLog(@"Main hello world");
YDPerson *person = [[YDPerson alloc]init];
}
return 0;
}
最后 打印顺序呈现

2020-03-29 16:11:40.334851+0800 objc-debug[11044:739044] load +[YDPerson load]

2020-03-29 16:11:40.364903+0800 objc-debug[11044:739044] load
2020-03-29 16:11:40.374489+0800 objc-debug[11044:739044] Main hello world
2020-03-29 16:11:40.380655+0800 objc-debug[11044:739044] 类的初始化 -[YDPerson init]
Program ended with exit code: 0

懒加载类和非懒加载类

1 懒加载类:真正调用的时候才开始加载,你真正用到我了,我才把你实现,什么时候用,什么时候实现,调用循序,在发送信息的时候也就是真正调用的时候 系统判断!cls->isRealized如果没被读取的话则用realizeClassMaybeSwiftAndLeaveLocked该方法去实现类的处理

2 非懒加载类:实现load()方法,编译器就开始执行,realizeCLassWithoutSwift(cls)实现所有非懒加载的类(实例化对象的一些信息,例如rw); 

信息执行顺序:编译->读取类信息储存表结构->实例化对象的信息

坑点:

类的读取read_images中 realizeClassWithoutSwift(cls)中有这么两句代码

 supercls = realizeClassWithoutSwift(remapClass(cls->superclass));//加载父类

metacls = realizeClassWithoutSwift(remapClass(cls->ISA()));//加载元类

这说明在我们类的加载中,在加载该类的同时也会加载相应的父类,如果当前类是非懒加载类,那么该类会在系统编译时进行加载,与此同时,该类的父类也会进行加载.




分类加载

分类概述

上一段汇编代码,看看分类里面包含的信息

struct _category_t {	
    const char *name; // 谁的分类	
    struct _class_t *cls; // 类	
    const struct _method_list_t *instance_methods;//实例方法	
    const struct _method_list_t *class_methods;	//类方法
    const struct _protocol_list_t *protocols;	//协议
    const struct _prop_list_t *properties;//属性
};

里面的方法有分开储存,因为实例方法存在于对象里面,类方法存在于元类里面

分类加载

分类的加载分为以下四种情况

1 懒加载类+懒加载分类

类和分类都没有实现load的方法,则是当类发送消息的时候(调用的时候)先加载类信息然后加载分类信息实现顺序:消息发送的时候 - lookuporforward ->  realizeClassWithoutSwift -> methodlizeClass-> 直接走data()

2 懒加载类+非懒加载分类

 类似子类实现了,父类伴随实现的这一种情况,该情况是分类先加载信息(realizeClassWithoutSwift),判断父类没有加载的话,再进行加载父类(read_images - addUnattachedCategoryForClass),然后将分类信息进行存储到父类

3非懒加载类+懒加载分类

该类实现了load方法分类没有实现,则当类加载的时候,直接加载该分类,加载顺序:read_images -> realizeClassWithoutSwift >- methodlizeClass - 不需要添加表 - 直接在相应data() - ro

4 非懒加载类+非懒加载分类

类和分类都实现load方法,类和分类的加载都提前了,则主类首先加载的同时观看分类加载,如没有没有加载的话直接加载分类信息,进行存储;加载顺序: read_images -> realizeClassWithoutSwift -> methodlizeClass -> addUnattachedCategoryForClass -> 判断是否实现 - 这里看到上面一行就在read_images 实现了 -> if (cls->isRealized()) { remethodizeClass(cls); -> 实现类信息} -> attachCategories 加载分类数据进来

分类加载总的来说就是看要不要运行时去处理,懒加载分类编译时就确定,非懒加载的类分类则烤运行时来确定

That's all