iOS runtime之元素认知

Posted xiaoxiaobukuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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_tv.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_tv.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_tv.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

四、总计

以上是关于iOS runtime之元素认知的主要内容,如果未能解决你的问题,请参考以下文章

jQuery文档操作之克隆操作

iOS开发笔记之Runtime实用总结

iOS开发之Runtime常用示例总结

我所认知的BIOS—&gt; uEFI AHCI Driver AtaAtapiPassThruSupported的局部变量们

iOS开发之Runtime常用示例总结

ios之runtime