runtime源码解读--数据结构

以下所有源码都是基于objc-2.0

1.类和对象

@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}

typedef struct objc_class *Class;
typedef struct objc_object *id;

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
    class_rw_t *data() { 
        return bits.data();
    }
    ...
}

struct objc_object {
private:
    isa_t isa;
    ...
};

union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
    ...
    };

类大部分的数据存放在bits.data()里,看看class_rw_t

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint32_t version;

    const class_ro_t *ro;

    method_array_t methods;
    property_array_t properties;
    protocol_array_t protocols;

    Class firstSubclass;
    Class nextSiblingClass;
    ...
};

这里可以看到方法列表、属性列表、协议列表,但是还差一个成员列表,这个存放在class_ro_t,这个指针类型是常量,说明在编译器就决定了。这个结构里也有属性、协议、方法列表,和上面的比较起来,就是这里是在编译器生成的,上面的是在运行时动态生成的。

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    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;
    }
};

参考链接:
深入解析 ObjC 中方法的结构

2. method SEL IMP

每个class都有个method列表,数据结构如下

struct method_t {
    SEL name;
    const char *types;
    IMP imp;
    ...
};

数据结构

typedef struct objc_selector *SEL;

但是源码里没有objc_selector的定义,通过查阅资料,SEL在不同编译环境定义不同,可以找到GNU环境下的定义

struct objc_selector
{
  void *sel_id;
  const char *sel_types;
};
//include/onx/runtime/[selector.h]

所以我猜测SEL只是保存了函数的标签。看下IMP的定义

#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id (*IMP)(id, SEL, ...); 
#endif

IMP是函数指针,指向了真正的函数实现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,840评论 0 9
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 2,237评论 0 7
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,667评论 33 466
  • 继上Runtime梳理(四) 通过前面的学习,我们了解到Objective-C的动态特性:Objective-C不...
    小名一峰阅读 786评论 0 3
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 778评论 0 2