iOS runtime之元素认知(一)

一、什么是runtime

简而言之,Objective-C Runtime是一个将C语言转化为面向对象语言的扩展。
我们将C++Objective进行对比,虽然C++Objective-C都是在C的基础上加入面向对象的特性扩充而成的程序设计语言,但二者实现的机制差异很大。C++是基于静态类型,而Objective-C是基于动态运行时类型。也就是说用C++编写的程序编译时就直接编译成了可令机器读懂的机器语言;用Objective-C编写的程序不能直接编译成可令机器读懂的机器语言,而是在程序运行的时候,通过Runtime把程序转为可令机器读懂的机器语言。RuntimeObjective不可缺少的重要一部分。

Runtime其实有两个版本: “modern” 和 “legacy”。我们现在用的 Objective-C 2.0 采用的是现行 (Modern) 版的 Runtime 系统,只能运行在 iOSmacOS 10.5 之后的 64 位程序中。而 macOS 较老的32位程序仍采用 Objective-C 1 中的(早期)Legacy 版本的 Runtime 系统。这两个版本最大的区别在于当你更改一个类的实例变量的布局时,在早期版本中你需要重新编译它的子类,而现行版就不需要。

runtime是一个c汇编写的动态库,它就像一个小小的系统,将OC和C紧密关联,这个系统主要做两件事 :

  • 1、封装C语言的结构体和函数,让开发者在运行时创建、检查或者修改类、对象和方法等等。
  • 2、传递消息,找出方法的最终执行代码。
  • 1、无参数

OC定义方法

[receiver message]

runtime转化C语言的代码:

objc_msgSend(receiver, selector)
  • 2、有参数

OC定义方法

[receiver message:arg1 ...]

runtime转化C语言的代码:

objc_msgSend(receiver, selector, arg1, arg2, ...)
  • 3、多方法

OC定义方法

NSObject *object = [[NSObject alloc] init];

runtime转化C语言的代码:

objc_msgSend(objc_msgSend([NSObject class],@selector(alloc)),@selector(init));

二、与runtime交互

bjc 从三种不同的层级上与 Runtime 系统进行交互,分别是:

  • 通过 Objective-C 源代码
  • 通过 Foundation 框架的NSObject类定义的方法
  • 通过对 runtime 函数的直接调用。

1、Objective-C源代码

编写OC代码,程序在运行时,runtime会自动将OC转化成C语言代码。

2、NSObject的方法

Cocoa 中大多数类都继承于NSObject类,也就自然继承了它的方法。最特殊的例外是NSProxy,它是个抽象超类,它实现了一些消息转发有关的方法,可以通过继承它来实现一个其他类的替身类或是虚拟出一个不存在的类。

有的NSObject中的方法起到了抽象接口的作用,比如description方法需要你重载它并为你定义的类提供描述内容。NSObject还有些方法能在运行时获得类的信息,并检查一些特性,比如class返回对象的类;isKindOfClass:isMemberOfClass:则检查对象是否在指定的类继承体系中;respondsToSelector:检查对象能否响应指定的消息;conformsToProtocol:检查对象是否实现了指定协议类的方法;methodForSelector:则返回指定方法实现的地址。

3、Runtime的函数

Runtime 系统是一个由一系列函数和数据结构组成,具有公共接口的动态共享库。头文件存放于/usr/include/objc目录下。许多函数允许你用纯C代码来重复实现 Objc 中同样的功能。虽然有一些方法构成了NSObject类的基础,但是你在写 Objc 代码时一般不会直接用到这些函数的,除非是写一些 Objc 与其他语言的桥接或是底层的debug工作。

三、Runtime元素认知

objc_msgSend:方法,它的真身是这样的:

id objc_msgSend ( id self, SEL op, ... );

1、objc_object

在这里插入图片描述

objc_msgSend第一个参数类型为id,它是一个指向类实例的指针:

// objc-private.h
typedef struct objc_object *id;

objc_object定义如下:

// objc-private.h
struct objc_object {
private:
    isa_t isa;
}

2、objc_class

在这里插入图片描述

// objc-private.h
typedef struct objc_class *Class;

objc_class定义如下:

//objc-runtime-new.h
struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
}

3、isa_t

在这里插入图片描述

isa的指向

  • 关于对象,其指向类对象;
    在这里插入图片描述
  • 关于类对象,其指向元类对象;在这里插入图片描述

4、cache_t

  • 用于快速查找方法执行函数
  • 是可增量扩展的哈希表结构
  • 是局部性原理的最佳应用

在这里插入图片描述
cache_t的定义如下:

//objc-runtime-new.h
struct cache_t {
	static bucket_t *emptyBuckets();
	
    struct bucket_t *buckets();
    mask_t mask();
    mask_t occupied();
    void incrementOccupied();
    void setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask);
    void initializeToEmpty();

    unsigned capacity();
    bool isConstantEmptyCache();
    bool canBeFreed();
};

5、class_data_bits_t

  • class_data_bits_t主要是对class_rw_t的封装
  • class_rw_t代表了类相关的读写信息、对class_ro_t的封装
  • class_ro_t代表了类相关的只读信息

class_data_bits_t定义如下:

//objc-runtime-new.h
struct class_data_bits_t {
    // Values are the FAST_ flags above.
    uintptr_t bits;
public:
    class_rw_t* data() const {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
    const class_ro_t *safe_ro() {
        class_rw_t *maybe_rw = data();
        if (maybe_rw->flags & RW_REALIZED) {
            // maybe_rw is rw
            return maybe_rw->ro();
        } else {
            // maybe_rw is actually ro
            return (class_ro_t *)maybe_rw;
        }
    }
};

①、class_rw_t

在这里插入图片描述

//objc-runtime-new.h
struct class_rw_t {
public:
    const class_ro_t *ro() const {
        auto v = get_ro_or_rwe();
        if (slowpath(v.is<class_rw_ext_t *>())) {
            return v.get<class_rw_ext_t *>()->ro;
        }
        return v.get<const class_ro_t *>();
    }

    void set_ro(const class_ro_t *ro) {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            v.get<class_rw_ext_t *>()->ro = ro;
        } else {
            set_ro_or_rwe(ro);
        }
    }

    const method_array_t methods() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->methods;
        } else {
            return method_array_t{v.get<const class_ro_t *>()->baseMethods()};
        }
    }

    const property_array_t properties() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->properties;
        } else {
            return property_array_t{v.get<const class_ro_t *>()->baseProperties};
        }
    }

    const protocol_array_t protocols() const {
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>()->protocols;
        } else {
            return protocol_array_t{v.get<const class_ro_t *>()->baseProtocols};
        }
    }
};

②、class_ro_t

在这里插入图片描述

//objc-runtime-new.h
struct class_ro_t {
    const char * name;
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
    
    method_list_t *baseMethods() const {
        return baseMethodList;
    }
};

6、method_t

在这里插入图片描述
method_t的定义如下:

struct method_t {
    SEL name;
    const char *types;
    MethodListIMP imp;

    struct SortBySELAddress :
        public std::binary_function<const method_t&,
                                    const method_t&, bool>
    {
        bool operator() (const method_t& lhs,
                         const method_t& rhs)
        { return lhs.name < rhs.name; }
    };
};

①、types

在这里插入图片描述

四、总计

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoxiaobukuang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值