您的位置:首页 > 其它

OC 运行时机制的一些应用

2016-03-15 00:10 316 查看

前言

OC 的运行时机制(Runtime)这个词接触过 iOS 开发的人或多或少应该都听说过,有的人已经能够熟练掌握它的真谛,有的对其依然感觉神秘无比。诚然,即使不掌握 OC 的运行时机制并不影响开发者开发出优秀的 iOS 应用,但是了解运行时机制能够帮助开发者更加透彻的了解 OC 背后的故事,揭开高级语言壳子下面的东西。

应用场景

动态添加属性

我们都知道,分类(Category)是 OC 的一个重要的语法,它可以帮助开发者在类的外部扩充方法,保持原类的规模,方法在需要的时候分块声明和实现,然而 Category 并不能帮助我们方便的给原来的类扩充属性,如果我们在分类中如下添加属性:



会出现如下错误:



而利用 objc/runtime.h 库中的一些函数可以帮助我们在分类添加属性,具体如下:



这种应用场景在 SDWebImage 框架中多次出现,SDWebImage 框架大量使用了分类来给 UIKit 框架的种类扩充方法,而在有些情况下又不得不通过分类给原类扩充属性来达到框架的设计目的,比如:我们可以在
UIImageView+WebCache.m
中找到这样的使用场景:



动态检测模型属性
使用 KVC 进行字典转模型的时候,我们一般都会这样写:



这样写会有一个缺陷,就是当 server 返回的 json 数据比转成字典后属性比我们定义的模型属性多的时候,KVC 转换的时候会报
undefined key
错误,我们可以重写



改写原来方法默认的报异常的实现方式,这样就不会报错误。

其实,除这个方法进行字典转模型以外,我们可以使用运行时的一些方法动态的获取模型中的属性列表:



然后根据获得属性列表进行有针对性的赋值,达到字典转模型的目的:



这个方法也在 MJExtension 框架有所涉及,
NSObject+MJProperty.m
中的
+ (NSMutableArray *)properties
方法使用了这种方式获取了属性列表。

方法的交换(拦截)

因为 OC 是动态的语言,方法的调用并不是在编译阶段完全定死的,而是在运行的时候以发送消息的形式进行调用,所以这里就引出了一个比较受争议的做法,就是通过运行时的 api 对方法的调用进行交换,也就是所谓的 method swizzling。我们通过下面的例子演示一下,将系统的
[UIImage imageNamed:]
的方法与我们自己实现的
imageWithName:
方法进行交换:



这个地方需要注意的是:在自己写的需要交换的方法中,由于方法已经被交换了,不能在自己写的方法中使用imageNamed方法,否则会造成死循环。

修改对象中的私有属性

工作中可能会遇到一种情况,你的项目是一个维护有些时日的老项目,当有的时候实现一个功能需要修改基类中的一些属性,然而基类在定义的时候并未考虑到这个属性需要修改,所以在类扩展中进行的定义,没有暴露出来,由于考虑到基类在多个地方被使用,无法评估修改基类对于项目其他地方的影响,这个时候需要用运行时的机制对私有属性进行获取和修改:



这个例子中就在没有破坏类结构的前提下修改了
DZOldNavigationController
中的私有属性
_screenShotsList
的值。

文/CoCodeDZ(简书作者)

原文链接:http://www.jianshu.com/p/b686c52a8d88

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: