iOS运行时(runtime)探究一:重要概念

来源:互联网 发布:股票数据统计 编辑:程序博客网 时间:2024/06/01 22:49

iOS运行时简介

因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时。也就是说只有编译器是不够的,还需要一个运行时系统 (runtime system) 来执行编译后的代码。这就是 Objective-C Runtime 系统存在的意义,它是整个Objc运行框架的一块基石。

iOS运行时的一些概念

1.类:Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。objc_class结构体的定义如下

struct objc_class {    Class isa  OBJC_ISA_AVAILABILITY;#if !__OBJC2__    Class super_class                       OBJC2_UNAVAILABLE;  // 父类    const char *name                        OBJC2_UNAVAILABLE;  // 类名    long version                            OBJC2_UNAVAILABLE;  // 类的版本信息,默认为0    long info                               OBJC2_UNAVAILABLE;  // 类信息,供运行期使用的一些位标识    long instance_size                      OBJC2_UNAVAILABLE;  // 该类的实例变量大小    struct objc_ivar_list *ivars            OBJC2_UNAVAILABLE;  // 该类的成员变量链表    struct objc_method_list **methodLists   OBJC2_UNAVAILABLE;  // 方法定义的链表    struct objc_cache *cache                OBJC2_UNAVAILABLE;  // 方法缓存    struct objc_protocol_list *protocols    OBJC2_UNAVAILABLE;  // 协议链表#endif} OBJC2_UNAVAILABLE;

2.实例对象:既是objc_object表示的一个类的实例的结构体,它的定义如下

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

3.元类(Meta Class):meta-class是一个类对象的类。它存储着一个类的所有类方法。每个类都会有一个单独的meta-class。

4.方法调用过程:首先在本类中查找,如果没有就向父类中查找,然后响应该方法,最后把该方法添加到cache列表中,以后再调用该方法,直接从cache中取出相应的方法调用。

5.实例对象的isa指针指向对象所属类,类的isa指针指向元类,元类的isa指针指向根元类(根类的元类),根元类的isa指正指向自身。类的superclass指针指向父类,根类的superclass指针指向nil,根元类的superclass指针指向根类。如下图所示:
这里写图片描述

void testClass(id self, SEL _cmd){    NSObject *object = [[NSObject alloc] init];    NSLog(@"NSObject实例:%@, 地址:%p", object, object);    NSLog(@"NSObject类名:%@ 地址:%p,NSObject父类名:%@ 地址:%p", [object class], [object class], [object superclass], [object superclass]);    NSLog(@"MyObject实例:%@,%p", self, self);    NSLog(@"MyObject类名:%@ 地址:%p,MyObject父类名:%@ 地址:%p", [self class], [self class], [self superclass], [self superclass]);    Class currentClass;    Class superClass = [self class];    do {        currentClass = superClass;        superClass = class_getSuperclass(currentClass);        NSLog(@"当前类:%@ 地址:%p, 父类:%@ 地址:%p", currentClass, currentClass, superClass, superClass);    } while (superClass != NULL);    Class isaClass = [self class];    currentClass = NULL;    do {        currentClass = isaClass;        isaClass = object_getClass(currentClass);        NSLog(@"当前类:%@ 地址:%p,isa指针指向的类:%@ 地址:%p", currentClass, currentClass, isaClass, isaClass);    } while (!(currentClass == isaClass));}- (void)createClass{    //创建一个类,注意名称一定不能是已经存在的类    Class myObjectClass = objc_allocateClassPair([NSObject class], "MyObject", 0);    //向类中添加一个方法    class_addMethod(myObjectClass, @selector(testClass), (IMP)testClass, "v@:");    //注册类,注册后方能使用该类    objc_registerClassPair(myObjectClass);    id myObject = [[myObjectClass alloc] init];    [myObject performSelector:@selector(testClass)];}

打印如下:
这里写图片描述

6.super:super与self不同。self是类的一个隐藏参数,每个方法的实现的第一个参数即为self。而super并不是隐藏参数,它实际上只是一个”编译器标示符”,它负责告诉编译器,当调用viewDidLoad方法时,去调用父类的方法,而不是本类中的方法。而它实际上与self指向的是相同的消息接收者。
super的定义:

struct objc_super {     id receiver;//即消息的实际接收者     Class superClass;//指针当前类的父类 };

例证:

- (void)viewDidLoad {    [super viewDidLoad];    NSLog(@"self:%@ super:%@", self, super.class);}

打印如下:
这里写图片描述

7.SEL:SEL又叫选择器,是表示一个方法的selector的指针,本质上,SEL只是一个指向方法的指针(准确的说,只是一个根据方法名hash化了的KEY值,能唯一代表一个方法),它的存在只是为了加快方法的查询速度。其定义如下:

typedef struct objc_selector *SEL;

8.IMP:IMP实际上是一个函数指针,指向方法实现的首地址。SEL就是为了查找方法的最终实现IMP的。由于每个方法对应唯一的SEL,因此我们可以通过SEL方便快速准确地获得它所对应的IMP,查找过程将在下面讨论。取得IMP后,我们就获得了执行这个方法代码的入口点,此时,我们就可以像调用普通的C语言函数一样来使用这个函数指针了。其定义如下:

id (*IMP)(id, SEL, ...)

9.Method:既是objc_method表示的一个结构体,该结构体中包含一个SEL和IMP,实际上相当于在SEL和IMP之间作了一个映射。有了SEL,我们便可以找到对应的IMP,从而调用方法的实现代码。Method用于表示类定义中的方法,则定义如下:

typedef struct objc_method *Method;struct objc_method {    SEL method_name                 OBJC2_UNAVAILABLE;  // 方法名    char *method_types                  OBJC2_UNAVAILABLE;    IMP method_imp                      OBJC2_UNAVAILABLE;  // 方法实现}  
0 0
原创粉丝点击