《精通Objective-C》阅读笔记(运行时系统)

运行时系统的组成部分

Objective-C的运行时系统由两个主要部分构成:编译器和运行时系统库。

编译器

编译进程会接受Objective-C源文件并进行处理(该处理过程由词法分析、语法分析、代码生成和优化、汇编以及链接操作等阶段构成),生成构成可以执行程序的二进制文件。

运行时系统

1.类元素(接口、实现代码、协议、分类、方法、属性、实例变量)
2.类实例(对象);
3.对象消息传递(包括动态类型和动态绑定)
4.动态方法决议
5.动态加载
6.对象内省

1.生成对象消息传递代码

当编译器解析对象消息时,如[super viewDidLoad];
它会生成调用运行时系统库中函数objc_msgSend()代码,该函数将接收器、选择器和消息传递的参数作为输入参数。因此编译器会将源代码中的所有消息传递表达式,转换为调用运行时系统库objc_msgSend()的代码处理。
每条消息都是以动态方式处理的,这意味着接收器的类型和方法实际实现代码都是在运行程序时决定的。

2.生成类和对象的代码

当编译器解析含有类定义和对象的Objective-C源代码时,它会生成相应的运行时数据结构。Objective-C中的类和运行时系统库中的Class数据结构对应。Class数据类型是指带有objc_class标识符的不同命数据类型指针,如:typedef struct objc_class *Class;

objc_object数据类型

struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

当你编写的程序创建对象时,系统会为objc_object类型数据分配内存,这种数据由isa指针后跟实例变量的数据构成。
与Objective-C中id数据类型对应的运行时数据类型是一种C语言结构,改该结构中被定义为objc_object的指针

id数据类型的定义

typedef struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
} *id;

id就是一个带有objc_object标识符的、指向C语言结构的指针。

运行时系统库

运行时系统库数据类型

1.类定义数据结构(类、方法、实例变量、分类、IMP和SEL等);
2.实例数据类型(id、objc_object和objc_super);
3.值(BOOL)

函数分为以下几类

1.对象消息
2.类函数
3.实例函数
4.协议函数
5.方法函数
6.属性函数
7.选择器函数

动态加添加一个类,并未其添加方法

 //动态创建一个类
    id testClass = objc_allocateClassPair([NSObject class], "TestClass", 0);
    
    //获取description方法
    Method des = class_getInstanceMethod(testClass, @selector(description));
//    获取description方法同类型的type
    const char *type = method_getTypeEncoding(des);
    //动态添加方法
    class_addMethod(testClass, @selector(getter), (IMP)getter, type);
    
    //注册当前类
    objc_registerClassPair(testClass);
    
    id class1 = [[testClass alloc]init];
    //使用该类向添加的方法发送一个消息
    [class1 performSelector:@selector(getter)];

2.实现运行时系统的对象消息传递
运行时系统库含有可用于访问下列信息的函数:

1.对象的类定义:objc_getClass
2.类的父类:objc_getSuperClass
3.对象的元类定义:objc_getMetaClass
4类的名称:objc_getName
5.类的版本信息:objc_getVersion
6.以字节为单位的类尺寸:objc_getInstanceSize
7.类的实例变量列表:objc_copyIvarList
8.类的方法列表:objc_copyMethodList
9.类的协议列表:objc_copyProtocolList
10.类的属性列表:objc_copyProperyList

image.png

当程序向对象发送消息时,运行时系统会通过定义代码中的类方法缓存和虚函数表,查找类的实例方法,为了找到相应的方法,运行时系统会搜索整个类层次结构,找到该方法后,它就会执行该方法的实现代码。

通过虚函数表查找方法
运行时系统库定义了一种方法数据类型objc_method

struct objc_method {
    SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;
    char * _Nullable method_types                            OBJC2_UNAVAILABLE;
    IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE;
}   

method_name一个SEL类型的变量,它描述了方法的名称。
method_types描述了方法参数的数据类型
method_imp是一个类型为IMP的变量,它在方法被调用时提供方法的地址。

image.png

运行时,系统库会先搜索类方法缓存查找方法IMP(值方法实现代码的指针),如果没有找到,它会在其虚函数表中寻找方法IMP,如果找到了它就会将这个IMP存储到缓存中备用。


通过dyld共享缓存使选择器拥有唯一性

dyld是一种系统服务,同于定位和加载动态库,它含有共享缓存,能够使多个进程共享这个动态库。dyld共享缓存中还含有一个选择器表,从而运行时系统能够通过该缓存访问共享库和自动以类的选择器。因此,运行时系统能够通过dyId共享缓存获取共用库的选择器,而需要做的仅是为应用中的自定义类更新选择器。

元类(metaclass)是一种特殊的类对象,运行时系统使用其中含有的信息能够找到并调用类方法。在Objective-C中,每个类都拥有一个独一无二的元类,因为每个类有可能拥有一个独一无二的类方法列表。

你可能感兴趣的:(《精通Objective-C》阅读笔记(运行时系统))