《OC理论底层详解篇之runtime运行时 》

谈到runtime我们不免想到isa指针。那什么是isa指针呢?OC语言里面每个对象都会有一个隐藏的数据结构,这个数据结构同时是OC对象的第一个成员变量。其实这个数据结构就是我们的isa指针。

那么isa指针有什么作用呢?那我们接下来看一下isa的指针的作用。

 isa指针通常用来指向对象所属的类,从而通过调用方法时通过isa指针找到相应的方法和属性。(元类的isa指针指向的就是元类)。

接下来我们看一下isa历史优化。

在arm64架构之前,isa就是一个普通的指针,储存着Class,Meta-Class对象的内存地址。

从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来储存更多的信息。

接下来我们谈谈位域位域储存了哪些信息?

首先我们看一下 nonpointer 这个里面存在0种情况 如果是0,就是说明是arm64架构之前。1代表已经优化过了,也就是arm64架构之后的。

接下来我们看一下has_assoc  这个作用是否有设置过关联对象,如果没有释放时会更快。

接下来我们看一下has_cxx_dtor  这个作用是否有C++析构函数,如果没有释放会更快。

接下来我们看一下shiftcls   这个里面储存着Class,Meta-Class对象的内存地址。

接下来我们看一下  magic  这个用于在调试时分辨对象是否完成初始化。

接下来再看一下 weakly_referenced  这个是判断是否被弱引用指向过,如果没有,释放时会更快。

接下来再看一下   deallocating  这个主要判断对象是否正在释放。

接下来再看一下   extra_rc 里面储存的值是引用计数减1

接下来再看一       has_sidetable_rc  判断引用计数器是否过大无法储存在isa中,如果为1那么引用计数会储存在一个叫SideTable的类的属性中。

然后我们看一下Class结构

接下来我们分析一下  class_rw_t。这个里面的方法,属性,协议是二维数组,可读可写,包含了类的初始化内容,分类的内容。

接下来我们分析一下  class_ro_t。 这个里面基类方法,基类协议,基类属性,成员变量,是只读的,包含了类的初始化内容。

接下来我们分析一下method_t。 这个是对方发/函数的封装。接下来我们看一下method_t的样子

SEL代表方法/函数名,一般叫做选择器。

可以通过@selector()和sel_registerName()获得。

可以通过sel_getName()和NSStringFromSelector()转成字符串。

不同类中的相同名字的方法,所对应的方法选择器是一样的。 我们看一下 typedef struct objc_selector * SEL 。

types包含了函数的返回值,参数编码的字符串。

接下来我们谈一下方法缓存  也就是cache_t  接下来我们看一下它的样子

其内部是用散列表(哈希表)  来缓存曾经调用的方法,从而提高方法的速度。

isa我们暂时介绍这么多。接下来重头戏来了,也就是我们的消息转发机制。哦,不对还没有谈runtime? 什么是runtime?

OC是一门动态性比较轻的编程语言,允许很多操作推迟到程序运行时再近些,OC的动态性就是由runtime来支撑和实现的,runTime是一套C语言的API,封装了很多动态性相关的函数,平时编写的OC代码,底层都是转换成了Runtime API进行调用。

runtime的具体应用

利用关联对象(AssociatedObject) 给分类添加属性

遍历类的所有成员变量 (修改textfield的占位文字的颜色,字典转模型,自动归档解档)

交换方法实现(交换系统的方法)

利用消息转发机制解决方法找不到的异常问题


OC中的方法调用,其实都是转换为objc_msgSend函数的调用。

其流程大致分为,消息发送(当前类,父类中查找),动态方法解析,消息转发三大阶段。

OC中的方法调用其实都是转成了objc_msgSend函数的调用,receiver(方法调用者)发送了一条消息(selector方法名)

我们先看第二个流程---------消息发送(当前类,父类中查找)

我们首先判断当前方法的调用者是否为存在,如果不存在我们则去看方法调用者的父类是否存在。

如果当前类存在-》我们就去方法的缓存中找-》方法里面去找

// 下面这条链找到了方法就会缓存到缓存方法里面

-》父类缓存方法中找  -》父类方法中找

//  已经排序的,二分查找法    没有排序的,遍历查找  

//  调用者通过isa指针找到调用者的类

//  调用者通过父类指针找到父类


我们接下来看第一个流程    动态方法解析 

如果调用了对象方法首先会进行+(BOOL)resolveInstanceMethod:(SEL)sel判断

如果调用了类方法 首先会进行 +(BOOL)resolveClassMethod:(SEL)sel判断

同时上面2个方法来动态添加方法实现

动态解析后,会重新走"消息发送"的流程

从当前类的缓存方法中查找方法开始

最后我们来看消息转发的第三个流程  消息转发

//  快速转发 返回值===nil 则往下走

-(id)forwardingTargetForSelector:(SEL)aSelector{}

//  常规转发

-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector


©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,883评论 0 9
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 6,469评论 0 9
  • 简介 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 O...
    随风飘荡的小逗逼阅读 4,687评论 0 0
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,887评论 1 32
  • 一、Runtime简介 Runtime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消...
    林安530阅读 4,687评论 0 2

友情链接更多精彩内容