几个基本的概念:

id,
id的定义是,
typedef struct objc_object {
Class isa;
} *id;

id是指向struct objc_object的一个指针。
这个意思是,id是一个指向任何一个继承了NSObject的对象,可以指向任意一个NSObject子类的对象。
需要注意的是id是一个指针,所以在使用id的时候不需要加星号。

SEL
SEL的定义是,
typedef struct objc_selector *SEL;
是指向 struct objc_selector的指针,而 objc_selector 的定义并没有在runtime.h中给出定义。

Objective-C在编译时,会根据方法的名字生成一个用来区分这个方法的唯一的一个ID。只要方法名称相同,那么它们的ID就是相同的。

说白了SEL是一个方法的方法名。

不同类的实例对象执行相同的selector时,会在各自的方法列表中去根据selector去寻找自己对应的IMP。

IMP
IMP的定义是,
typedef id (*IMP)(id, SEL, …);
为方法具体实现代码块的地址,可像普通C函数一样调用。
是指向一个函数的一个指针。这个被指向的函数包括一个id(标识是哪个instance或者class的方法),一个SEL(标识是哪个方法),以及函数的入参以及返回值。
说白了,IMP指向实现代码。

Method
Method,也就是我们说的方法,
在objc/objc-class.h中是这样定义的:

struct objc_method
{
SEL method_name;
char * method_types;
IMP method_imp;
};

一个方法Method,包含了一个方法名SEL,一个指向方法实现地址的指针IMP,以及入参和出参的描述字符串。

==

iOS的实例,对象,元类

参考唐巧的这篇博客:http://blog.devtang.com/2013/10/15/objective-c-object-model/

实例

instance of class的内存结构里存储了isa指针,以及instance的成员变量。

类的实例看成一个 C 语言的结构体(struct),上面说的 isa 指针就是这个结构体的第一个成员变量,而类的其它成员变量依次排列在结构体中。

isa指向实例的类对象Class。Class中又存储了Class的isa 和super Class指针,以及实例的实例方法等其他list指针,Class的isa指向元类。元类的isa指向根元类,根元类的isa指向自身,这样就形成了isa指针的闭环。也形成了属性和方法存储和查找的闭环。

因为对象在内存中的排布可以看成一个结构体,该结构体的大小并不能动态变化。所以无法在运行时动态给对象增加成员变量。

相对的,对象的方法定义都保存在类的可变区域中。方法的定义列表是一个名为 methodLists的指针的指针(如下图所示)。通过修改该指针指向的指针的值,就可以实现动态地为某一个类增加成员方法。这也是Category实现的原理。同时也说明了为什么Category只可为对象增加成员方法,却不能增加成员变量。

**:特别说明一下,通过objc_setAssociatedObject 和 objc_getAssociatedObject方法可以变相地给对象增加成员变量,但由于实现机制不一样,所以并不是真正改变了对象的内存结构。

Class

每一个对象都是一个类的实例。在 Objective-C 语言的内部,每一个对象都有一个名为 isa 的指针,指向该对象的类。每一个类描述了一系列它的实例的特点,包括成员变量的列表,成员函数的列表等。每一个对象都可以接受消息,而对象能够接收的消息列表是保存在它所对应的类中。

Meta-Class

因为类也是一个对象,那它也必须是另一个类的实列,这个类就是元类 (metaclass)。元类保存了类方法的列表。当一个类方法被调用时,元类会首先查找它本身是否有该类方法的实现,如果没有,则该元类会向它的父类查找该方法,直到一直找到继承链的头。

这三部分的闭环结构见上。

【引】runtime全解析,P2:关于Class 和 MetaClass的更多相关文章

  1. 【引】runtime全解析,P1:Programming Guide

    h2.Overview Objective-C language defers as many decisions as it can from compile time and link time ...

  2. 【凯子哥带你学Framework】Activity界面显示全解析

    前几天凯子哥写的Framework层的解析文章<Activity启动过程全解析>,反响还不错,这说明“写让大家都能看懂的Framework解析文章”的思想是基本正确的. 我个人觉得,深入分 ...

  3. Dagger2 使用全解析

    Dagger2 使用全解析 Dagger是一个注入工具,何为注入,我们要生产一批机器人,每个机器人都有一个控制器,我们可以在机器人内部 new 出一个控制器: class Robot { val co ...

  4. oracle提高查询效率的34个方面全解析

    oracle提高查询效率的34个方面全解析   在一个数据库中进行操作的时候,效率是很重要的,那么,如何提高oracle的查询效率呢?笔者将从以下几个方面进行详细解析: 1.选择最有效率的表名顺序(只 ...

  5. OC分类(类目/类别) 和 类扩展 - 全解析

    OC分类(类目/类别) 和 类扩展 - 全解析   具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...

  6. PHP 类与对象 全解析(三)

    目录 PHP 类与对象 全解析( 一) PHP 类与对象 全解析( 二) PHP 类与对象 全解析(三 ) 13.魔术方法 定义:PHP把所有以__(两个下划线)开头的类方法当成魔术方法     __ ...

  7. Android图片加载框架最全解析(六),探究Glide的自定义模块功能

    不知不觉中,我们的Glide系列教程已经到了第六篇了,距离第一篇Glide的基本用法发布已经过去了半年的时间.在这半年中,我们通过用法讲解和源码分析配合学习的方式,将Glide的方方面面都研究了个遍, ...

  8. Android图片加载框架最全解析(三),深入探究Glide的缓存机制

    在本系列的上一篇文章中,我带着大家一起阅读了一遍Glide的源码,初步了解了这个强大的图片加载框架的基本执行流程. 不过,上一篇文章只能说是比较粗略地阅读了Glide整个执行流程方面的源码,搞明白了G ...

  9. C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入

    C# 嵌入dll   在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...

随机推荐

  1. Andriod Studio adb.exe,start-server' failed -- run manually if necessary 解决

    首先查看了我的任务管理器,共有三个adb的程序在运行: 错误提示的是 Andriod Studio 中的adb.exe启动失败,于是,去关掉另外两个adb.exe,两分钟左右后,又出现了三个adb. ...

  2. 惯性导航之MEMS加速度计原理

    一 加速度计原理 1.1 加速度计由MEMS传感器与信号处理芯片组成. 1.2 MEMS加速度计工作原理 由上电容.中电容板(可移动).下电容板等组成:当加速度达到一定值后,中电容板会移动,与上.下电 ...

  3. 使用CSS3动画属性实现360°无限循环旋转【代码片段】

    使用CSS3的animation动画属性实现360°无限循环旋转. 代码片段: <div id="test"> <img src="/CSS3/img/ ...

  4. shell 简单计算脚本

  5. php绘图问题

    php绘图首先要确认gd库是否启用,到php.ini文件中,找到extension=php_gd2.dll将前面的:去掉,重新启动服务器. 如果在绘图中还是没有显示正常的图片,说明服务器在回复请求时, ...

  6. 学习NSRulerView

    NSRulerMarker 有个imageOrigin是描述Marker中image的位置的: 在horizontal的ruler中,imageOrigin的x坐标是跟marker的location进 ...

  7. DOM扩展之HTML5 插入标记

    11.3.6 插入标记 当需要在文档中插入大量的HTML标记时,通过DOM操作就会是非常麻烦的,相对而言,使用插入标记的技术,直接插入HTML字符串不仅简单而且更快.以下插入标记相关的DOM操作已经纳 ...

  8. js 布尔值作为开关判断

    var flag = true; $("#more_info").click(function() { if( flag ){ $("#more_xl_more" ...

  9. vector容器使用和assert断言关键字

    C++里面的容器是个比较复杂的东西,我这篇只说vector容器怎么使用,详细的网搜. vector模板类其实是一个动态数组,跟自己用new关键字创建数组一样,只不过vector会自动帮我们用new和d ...

  10. xlwt写入中文操作不成功,提示UnicodeDecodeError: ascii codec can't decode byte ...

    打开xlwt包里的Workbook.py文件,修改Workbook类的__init__方法 将 def __init__(self, encoding='ascii', style_compressi ...