runtime

2017-08-30  本文已影响13人  sweetpf

作为iOS开发者,runtime特性是必须了解的重点加分项。这并不是说你可以说出消息机制,运行时消息重定向,或者利用runtime特性实现交换方法等,而是更应该深入了解其原理,"知其然且知其所以然"才能不断成长。
Object-C是面相运行时的语言(runtime oriented language),它将编译和链接时要执行的逻辑延迟到运行时来处理。相对静态语言,我们的代码更具灵活性,在苹果封闭链中这个特性也能帮助我们进行线上修复,例如业界鼎鼎大名的JSPatch(虽然现在苹果为了安全性,一封邮件“封杀”JSPatch)。那本篇文章先从runtime功能入手,让你体会runtime的强大,再介绍其原理。在此之前,先了解下基础知识。

传送门

Objective-C 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 时会先查找类缓存。有个理论是,当你在一个类上调用了一个消息,你很可能之后还会调用它。

runtime 常用开发应用场景

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 对官方文档的翻译,略显粗糙,适用于我这种英文比较烂的童鞋😂

上一篇 下一篇

猜你喜欢

热点阅读