iOS RunTime 机制浅析(一)
来源:互联网 发布:男双肩包推荐 知乎 编辑:程序博客网 时间:2024/05/20 18:44
最近在看某些书籍和博客的时候不时地有Runtime的出现,查了相关介绍之后觉得还是没有彻底地理解其机理,于是今天把官方文档给煲了一下,下面结合相关介绍,做一个相对全面的学习笔记。
Abstract
Runtime是Object-C特有的一种动态运行机制,compiler中的runtime system实现这种机制。
其主要在三方面实现:
第一是我们写的原代码,protocal、instance varible;
第二是Foundation Framework中的方法,如NSObject,NSProxy;
第三是直接使用plain C纯C语言的方法来实现。
接下来我们来看看这三方面分别是怎样一种实现机理。
第一
主要是指消息机制,最典型的就是我们所写代码中的函数调用,便是通过runtime system来实现的。
在介绍其实现过程之前我们先来剖析objc中的类变量是如何在内存中组织的。
在我们创建一个类的时候,系统会为这个类分配一段内存空间,用来存放其属性变量。而在这些属性变量的最开始,也就是内存的第一个空间,存放着每个类所特有的isa指针,如图fig-1.1。
这个指针指向的是这个类的信息结构体class structures,结构体由两个变量组成,一个指向父类structures的指针还有一个指向类方法地址表格methor address table的指针,如图fig-1.2,图fig-1.3。由最小子类向上攀升,isa一层层向上指,直至NSObject基类。
有了类在内存中组织的结构的概念之后,我们再来分析我们所写代码的消息机制如何在runtime 中实现。
当我们在代码中调用某一函数,比如:
[object methor];那么经runtime system时将会调用
objc_msgSend(receiver,selector);来告知receiver调用selector函数。
再receiver类收到消息之后,其会启动一下过程寻找函数的实现IMP地址。
首先在私有内存空间中通过isa找到class structures,随后访问methor table,看是否有对应函数地址存在,如有便返回,如没有则通过super class structures pointer继续向上层的methor table寻找,直至寻找到对应的IMP地址或到NSObject都没找到则返回错误信息。假如找到对应的函数地址则调用并返回返回值,如图 fig-1.4。
为了防止每次寻找地址空间耗费过多的时间,runtime system准备了一个cache table来存放已经找到的函数地址空间,当一个函数调用多次时便可以节省寻找时间,所以receiver 接收到消息之后应该是先在cache table中寻找,找不到时在执行后续的寻找,如下图fig-1.5。
以上便是objc中通过rumtime实现函数的调用过程。
值得一提的是在objc_msgSend函数中的receiver和selector函数实际上的隐藏参数,因为在objc层面其并没有直接显示出来。
不过这两个参数还是有作用的,特别是self参数,如下(引用自官方文档):
- strange{ id target = getTheReceiver(); SEL method = getTheMethod(); if ( target == self || method == _cmd ) return nil; return [target performSelector:method];}对于以上函数,我不是很理解,大家多多指教。
第二
runtime interact with methor in Foundation Framework这方面主要指的是NSObject提供的通过runtime system实现的函数,如description方法,其返回一段对于类的描述,最典型是用于debugge,比如数字类返回的是对于成员的描述。其他的诸如
isKindOfClass:
isMemberOfClass:
respondsToSelector:
conformsToProtocol:
methodForSelector:等通过runtime实现的包含在NSObject的函数,值得注意的是这些函数并不是objc函数,而是由runtime system提供的函数。
当我们在一个loop循环中持续调用某个函数时,这会频繁的通过runtime去寻找函数实现地址,如第一点中所提到的过程,此时circumvent dynamic binding,绕过runtime动态绑定而调用函数的方法便是使用methorforSelector:直接找到函数的地址,这样在多次的循环中,可以节省很多时间。
其次重要的方面便是通过runtime system进行方法的动态implementation实现。
对属性声明
@dynamic propertyName;
告诉编译器这个属性有关的方法是动态生成的,进而编写函数实现代码
void dynamicMethodIMP(id self, SEL _cmd) { // implementation ....}以及动态生成过程
@implementation MyClass+ (BOOL)resolveInstanceMethod:(SEL)aSEL{ if (aSEL == @selector(resolveThisMethodDynamically)) { class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:"); return YES; } return [super resolveInstanceMethod:aSEL];}@end
当检测到SEL是
resolveThisMethodDynamically
即动态实现函数时,便调用class_addMethod来动态实现。比较常见的便是coredata中关联类的属性声明。
动态加载机制为objc解决了很多事情,实现了很多功能,当类被创建时,协议被创建时我们都可以在运行时动态地添加相关功能module。Cocoa框架中有很多也是通过动态加载来实现的。
第二点最后一个内容是forwarding Message的由runtime system提供消息转发机制,关于剩下的部分在下一篇中会提到。未完待续。。
- iOS RunTime 机制浅析(一)
- iOS runtime 机制浅析
- iOS RunTime 机制浅析(二)
- IOS Runtime(一)
- iOS Runtime(一)
- iOS Runtime(消息机制)
- RunTime机制详解(一)
- iOS的runtime浅析
- iOS Runtime总结(一)
- iOS 【iOS Runtime浅析(2):消息转发】
- iOS 【iOS Runtime浅析(3):Method Swizzling】
- IOS 运行时(runtime)机制
- iOS runtime 机制
- 【iOS开发】runtime机制
- iOS runTime 机制详解
- iOS runtime机制
- iOS runtime机制
- iOS - runtime机制
- Linux协议栈-netfilter(5)-iptables
- 设计模式之--Facade模式
- 【SeedCoder 2015年热身】写在最前面的话
- C语言 编写一个函数,传入a,b两个int类型的变量,返回两个值的最大公约数。
- Islands Travel——SPFA求最短路
- iOS RunTime 机制浅析(一)
- 文章标题
- windows下用脚本设置环境变量
- 前端资源收集
- C语言 编写一个函数实现n^k,使用递归实现
- 阿里ECS服务器CentOS Linux系统安装MySQL-5.5.27
- 25岁了,做一个男人该做的事
- c#备忘录(1)
- ubuntu 配置java环境装上Sublime Text 2