1.给category添加属性
应用场景:比如MJRefresh的封装,直接往tableview或者collectionview的父类scrollview创建分类,然后把MJRefresh动态添加到分类里面。就无需每一个要刷新的view都定义一次了。或者往button,view里面添加tag的属性。这些都可以用runtime来做
在Runtime源码中有两个非常重要的头文件“objc/runtime.h”、“objc/message.h”,第一个文件里面实现了很多类相关的操作,第二个文件主要处理OC调用方法时所发送的消息。当我们要调用Runtime的API时,一般要导入这两个头文件。
首先必须引入objc/runtime.h库然后我给uibutton添加一个分类,让给往里面加属性。试试运行,结果报错。错误内容如下
而且编译时会有警告。
接着我写了get/set函数,里面运用runtime的方法,关联属性到category里面。
get方法最后运行,属性添加成功了
或者扩大button的点击范围
当中有一个方法:- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
手指触碰(touch)=》 放入UIApplication事件队列 =》 事件传给window对象 =》window调用hitTest:withEvent:方法找初始触碰点的view (具体window的实现:在最顶层的子视图subview上调用hitTest:withEvent:=》然后subview上面的由top到buttom,最上面的子视图开始,每个视图都调用pointInside:withEvent =》若返回yes,继续逐级调用,直到找到触碰点的位置,直到返回非空,则hitTest:withEvent返回该对象,若返回nil,则返回自身self)
2.方法动态添加
应用场景:当一个类里面有很多方法时,我们需要消耗很多内存去加载这个类。因为要给每个类生成映射表。而且可以调用一个未实现的方法和去除报错
而我在此就有疑问:1.那为了节省内存,可以所有方法都动态添加吗? 2.为什么会调用一个没实现的方法呢?既然报错,不是应该去完成这个方法的实现吗?
后来我网上搜了很久。仍然找不到答案。最后再回顾应用场景的那句话。“当一个类里面有很多方法时”,那我觉得运用runtime来添加方法的条件:是这个类里面有很多方法。内存资源占据了很多的时候,可以用这个runtime添加方法。
3. 方法替换
创建uibutton 为UIbutton点击间隔时间创建get/set方法 在category文件里面替换button的触发方法。利用GCD线程应用场景:防止uibutton或者UITapGestureRecognizer的暴力点击,也可以扩展uibutton的点击范围等等
4.归档与解档
5. kvo的实现(动态添加类)
当你观察一个对象时,系统会执行方法
“- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;”
后,一个新的类会运用runtime动态被创建。再用 runtime 动态添加self.person 对象的一些属性如 observe 观察者(strong 强引用,这也解释了为什么每个 dealloc 方法内需要移除监听 )。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。然后,重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象值的更改。最后把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象被偷偷新创建的子类的实例。原来,这个中间类,继承自原本的那个类。不仅如此,Apple 还重写了 -class 方法,且我们这个类没有变,就是原本那个类。
适合于运用在Molde与controller之间的通讯
6.JSPatch 与 runtime
应用场景:当我们发布了app之后,发现代码中有错误。我们无法即使修改更新。这时候我们可以引入JSPatch这个第三方库。他可以将OC语言转为JS脚本语言。然后动态的替换项目里面的原生代码,达到动态修复bug的作用
7.字典转模型model
应用场景:当我们请求数据是json的字典类型。这时候要将字典赋值给对象里面的属性。就可以用到runtime
网友评论