初探Runtime:它到底是什么?
说实话,很多iOS开发者干了三五年,天天跟Objective-C打交道,却未必真正理解Runtime是什么。
我刚开始接触iOS开发时,也以为Runtime就是个黑盒子。直到有一次,我在一个大型项目中遇到了消息转发的问题——某个对象收到了无法识别的selector,程序直接崩溃了。那时候我才意识到,不懂Runtime,你连崩溃日志都看不懂。
Runtime,全称是Objective-C Runtime。说白了,它是一套用C和汇编写的底层库。这套库给Objective-C加上了动态特性。你想想看,我们平时写的OC代码,最终都会转换成Runtime的C函数调用。
举个例子:
// 我们写的OC代码
[obj doSomething];
// 编译器会转换成
objc_msgSend(obj, @selector(doSomething));
嗯,就是这么回事。你写的每一行OC代码,背后都是Runtime在默默工作。
Runtime的核心价值
Runtime到底牛在哪?我总结了三个核心价值,这也是我在项目中反复体会到的。
1. 动态消息派发
这是Runtime最基础的能力。对象调用方法,不是编译时决定的,而是运行时才去查找。
为什么会这样?因为OC的消息机制是松耦合的。发送消息的对象不关心接收者是谁,接收者也不关心消息从哪来。这种设计让代码变得非常灵活。
我在项目中遇到过这样一个场景:我们需要给所有UIViewController统一添加日志埋点。如果不用Runtime,你得手动在每个VC里写代码。用了Runtime,直接hook掉viewDidLoad方法,一行代码搞定所有VC。
2. 动态方法解析与消息转发
这个能力,说白了就是给程序留了"后悔药"。
当一个对象收到无法处理的消息时,Runtime不会直接崩溃。它会给你三次机会:
- 动态方法解析:问你能不能动态添加一个方法
- 快速转发:问你能不能把消息转发给别的对象
- 完整转发:给你完整的NSInvocation,让你自己决定怎么处理
我曾经用这个机制做过一个"防崩溃"框架。当某个对象收到未实现的方法时,不直接崩溃,而是记录日志并返回一个默认值。嗯,这个框架后来成了我们团队的标配。
3. 关联对象与分类属性
OC的分类有个限制:不能添加存储属性。但Runtime的关联对象机制打破了这限制。
// 给分类添加属性
static char kAssociatedKey;
- (void)setCustomProperty:(NSString *)value {
objc_setAssociatedObject(self, &kAssociatedKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)customProperty {
return objc_getAssociatedObject(self, &kAssociatedKey);
}
这个技巧我在很多项目里都用过。比如给UIImageView添加一个下载任务的属性,方便取消操作。
为什么iOS开发者要学Runtime?
这个问题,我经常被问到。我的回答很简单:不懂Runtime,你永远只是个"调API"的开发者。
具体来说,有这几个原因:
面试必考
你去面中高级iOS岗位,Runtime几乎是必问的。消息转发流程、isa指针、method swizzling...这些都是高频考点。我面试过不少人,能讲清楚Runtime的,通常基础都不差。
解决疑难杂症
有些Bug,不用Runtime根本查不出来。比如某个对象莫名其妙收到了消息,或者某个方法被覆盖了。这时候,你得用Runtime的API去动态查看类结构、方法列表。
实现高级功能
热修复、AOP编程、JSON自动转模型...这些高级功能,底层都依赖Runtime。我做过一个JSON转模型的框架,核心就是利用Runtime获取类的属性列表,然后动态赋值。
核心观点:Runtime不是锦上添花的知识,而是iOS开发的底层基石。你越早掌握它,就越能理解OC的设计哲学。
Runtime的知识体系
为了让你对Runtime有个整体认识,我画了一张图:
学习建议:别急着啃源码。先理解Runtime能做什么,再去看它怎么做的。我当初就是先学会了Method Swizzling,才反过来研究消息转发流程的。
避坑指南:我曾经在一个线上项目里滥用Method Swizzling,结果导致多个第三方库的方法互相覆盖,排查了整整两天。记住:Runtime能力越强,责任越大。生产环境慎用。
总结
Runtime是OC的灵魂。它让这门语言拥有了动态能力,也让iOS开发有了无限可能。
从消息派发到动态方法解析,从关联对象到底层数据结构,每一个知识点都值得你花时间去啃。别怕难,我当初也是一步步走过来的。
嗯,这一章先带你入门。后面的章节,我们会深入每个细节,用代码说话。
公众号:蓝海资料掘金营,微信deep3321