作为iOS开发者,runtime特性是必须了解的重点加分项。这并不是说你可以说出消息机制,运行时消息重定向,或者利用runtime特性实现交换方法等,而是更应该深入了解其原理,"知其然且知其所以然"才能不断成长。 Object-C是面相运行时的语言(runtime oriented language),它将编译和链接时要执行的逻辑延迟到运行时来处理。相对静态语言,我们的代码更具灵活性,在苹果封闭链中这个特性也能帮助我们进行线上修复,例如业界鼎鼎大名的JSPatch(虽然现在苹果为了安全性,一封邮件“封杀”JSPatch)。那本篇文章先从runtime功能入手,让你体会runtime的强大,再介绍其原理。在此之前,先了解下基础知识。
Object-C的runtime是一个运行时库(官方传送门:https://opensource.apple.com/tarballs/objc4/),是一套纯C(C和汇编)API,感兴趣的可以下载官方源码。Objective-C runtime 创建了所有需要的结构体,让 Objective-C 的面相对象编程变为可能。
1、Objective-C runtime包括两个版本,Modern Runtime和 Legacy Runtime:
2、Method 有 2 种基本类型的方法:
3、Selector Selector 在 Objective-C 中 selector 只是一个 C 的数据结构,用于表示一个你想在一个对象上执行的 Objective-C 方法。
4、Meta Classes 类类型
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
这段代码 5、objc_class Objective-C 中 NSObject是大多数类的根类。
@interface NSObject <NSObject> {
Class isa OBJC_ISA_AVAILABILITY;
}
从中可以看出NSObject有一个isa属性,类型是Class。Class 是一个 objc_class 结构类型的指针
struct objc_class {
struct objc_class *isa;
struct objc_class *super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
};
可以看到Objective-C对象系统的基石:struct objc_class结构如下:
6、objc_object objc_object 只有一个指向类的 isa 指针,就是我们说的术语 “isa pointer”(isa 指针)。
7、isa 指针 isa 指针是当你向对象发送消息时,Objective-C Runtime 检查一个对象并且查看它的类是什么然后开始查看它是否响应这些 selectors 所需要的一切。
8、id指针 id数据类型是一个指向struct objc_object结构的指针,这个指针包含一个纸箱objc_class结构的isa 指针。 更确切地说,id是指向Class类型的指针,而Class又是指向struct objc_class结构的指针。
9、 Class Cache 就是class_object定义中的struct objc_cache *cache; 当 Objective-C runtime 沿着一个对象的 isa 指针检查时,它会发现一个对象实现了许多的方法。然而你可能只调用其中一小部分的方法,也没有意义每次检查时搜索这个类的分发表(dispatch table)中的所有 selector。所以这个类实现了一个缓存,当你搜索一个类的分发表,并找到合适的 selector 后,就会把它放进缓存中。所以当 objc_msgSend() 在一个类中查找 selector 时会先查找类缓存。有个理论是,当你在一个类上调用了一个消息,你很可能之后还会调用它。
http://www.jianshu.com/p/19f280afcb24,“白开水”的这篇文章介绍的很好,标题“面试、工作”就赢了
利用runtime 可以做一些OC不容易实现的功能:
面试题 1、method swizzling?
2、objc中向一个对象发送消息[obj foo]和objc_msgSend()函数之间有什么关系? objc_msgSend()是[obj foo]的具体实现。 在runtime中,objc_msgSend()是一个c函数,[obj foo]会被翻译成这样的形式objc_msgSend(obj, foo)。 1、去obj的对应的类中找方法 2、先找缓存,找不到再去找方法列表, 3、再找父类,如此向上传递。 4、最后再找不到就要转发。
3、什么时候会报 Unrecognized selector 的异常? 当调用对象的某个方法的时候, 如果在当前类中没有找到此方法, 那么就到当前类的父类中去寻找, 如果在父类中没有找到, 那么就去父类的父类中去寻找, 一直找到 NSObject 都没有这个方法, 就会报 Unrecognized selector 的异常.
4、runtime如何通过selector找到对应的IMP地址?(分别考虑类方法和实例方法) IMP寻址 http://blog.csdn.net/dp948080952/article/details/52437451
5、_objc_msgForward函数是做什么的,直接调用它将会发生什么? http://www.jianshu.com/p/04ba5f3bfc2b
6、消息机制方法调用流程 方法:实例方法,类方法 http://www.jianshu.com/p/d5ca2cdd4fa7 对官方文档的翻译,略显粗糙,适用于我这种英文比较烂的童鞋?