前记
两年做了一个关于runtime的内部分享,当时是做了一个演示分享的keynote,列出一个自己要分享的内容的大概,然后具体分享的时候自己再去扩展,辅助一些操作演示,所以打算再组织一下语言,把之前分享的完整地通过书面形式呈现出来,希望能得到一些巩固。
关于runtime
我们都知道OC它是一门动态语言,所以它总是想办法把一些决定工作从编译链接推迟到运行时。Well, 这意味着只有编译器是不够的,还需要一个运行时系统,也就是runtime system来执行编译后的代码。所以,这就是OC runtime system存在的意义,它是整个OC运行框架的一块基石。
比较不为人所熟知的是runtime其实有两个版本,“modern”和 “legacy”,我们现在用的 Objective-C 2.0 采用的是现行(Modern)版的Runtime系统,只能运行在 iOS 和 OS X 10.5 之后的64位程序中。而OS X较老的32位程序仍采用 Objective-C 1中的(早期)Legacy 版本的 Runtime 系统。
开发过程中是怎样与runtime进行交互的
用“交互”可能不太好理解,说白了就是通过哪些途径去使用runtime的。主要有以下三种途径:
- Objective-C的源代码
- NSObject的方法
- 直接调用runtime的函数
我们先大致讲下这三点,第一点:通过OC的源代码,最常见的就是调用一个对象的方法[receiver message], 实际上,准确的说法应该是给receiver这个对象发送一个叫message的消息,编译器会在编译时把上面那句代码转换成objc_msgSend(receiver, selector, arg1, arg2, ...), arg1,arg2代表有传参数时的情况,算是比较基础的知识,原谅我的啰嗦....
第二点,NSObject中有封装了一些方法,比如:isKindOfClass, isMemberOfClass, respondsToSelector, conformToProtocol,methodForSelector,这些方法可以从runtime系统中获取信息,也就是允许这些对象进行自我检查,称为自省。
第三点,可以引入runtime的库,直接使用它提供给我们调用的方法。举一个非常常见的栗子:
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
为某一个对象创建关联对象的时候,可以通过以上方法动态添加,当然,这仅仅只是创建关联对象,获取的时候可以这么获取:
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
小结
打个不是很恰当的比方:如果把OC比作是人的一副驱壳,那么,runtime则是赋予这个驱壳生动生命的灵魂,用好runtime经常能起到事半功倍的效果,后续我们来着重探讨下它的妙用。