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

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;  // 方法实现

}  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值