废话开篇:RxSwift 在任务序列执行代码的最后面会调用 dispose() 或者 disposeBy() 方法,其实这里会有个疑问,那么 RxSwift 要销毁的到底是什么?因为在创建任务序列的过程中会创建很多相关联的对象来保障程序运行,说到底就是最外层的闭包进行下沉的过程中需要的对象,那么,在它们的销毁权限就转移给外界了,什么时候销毁,那么就根据程序的需要而定了。
# iOS 封装一个简易 UITableView 链式监听点击事件的功能思路与实现
# iOS 封装一个仿 RxDriver 简易 UITableView 数据源驱动绑定功能思路与实现
一、封装 Dispose 及 DisposeBag 的应用场景
先看一下要实现的逻辑:
dispose 方法调用直接销毁 链式内部创建的对象
DisposeBag 管理 链式内部创建的对象 销毁节点
之前的文章中并没有添加对 内部创建对象 的生命周期进行处理,为了保证程序的进行内部所有的对象均用 static 修饰,那么,创建 Dispose 和 DisposeBag 对 链式内部创建的对象 进行管理。
二、封装 Dispose
KDSDisposeBag.h
这里依然用方法返回 block 的形式进行封装。
KDSDisposeBag.m
先看一下 KDSDelegateProxy.m 里面的修改
之前圈出的 tableViewDelegateProxy 是一个 static 修饰的全局变量,那么现在换成一个临时变量。
在 UITableview 分类 UITableView+KDS.m 下的 rxRegistSelected 方法下创建一个 WSLDispose 保存一下 KDSDelegateProxy 提供的 UITableview 的代理 对象
运行一下代码,在 KDSDisposeBag 对象不执行 dispose 方法的前提下能不能持久化中间过程变量(这里就是 tableview 的代理)
直接销毁了,当然代理销毁了,再点击 cell 也就不可能执行点击事件中打印 indexPath 操作了,如下图:
为什么没有调用 dispose 就全部销毁了呢?其实原因很简单,全过程除了 block 中持有了 dispose 对象再无其他类持有,所以在 block 执行完成后就会直接销毁了,解决问题的关键就是让 tableView 关联上 dispose 就行了。
实现如下:
在 UITableview 分类 UITableView+KDS.m 里对 dispose 进行关联
修改 rxRegistSelected 方法
关联对象会在当前对象(UITableView)释放前进行取消关联操作后释放,所有,这里无需担心释放问题,当然,也可以设置关联对象的关联属性时为 OBJC_ASSOCIATION_ASSIGN,不增加引用计数。
好了,再运行一下代码
dispose 对象的生命周期是跟随 tableView 了,所以,并没有进行销毁,因此也控制台可以打印了。
那么,在调用一下 dispose 方法进行销毁试一下。
代理类销毁了,当然点击事件 block 也就不能执行了
因为 dispose 对象的生命周期是跟随 tableView ,所以,控制器销毁后 -> tableView 销毁 -> dispose 对象销毁
如图:
三、KDSDisposeBag 封装
KDSDisposeBag 的目的也很简单,就是将 KDSDispose 对象保存的待释放的中间对象的释放权转给 KDSDisposeBag 对象。
KDSDisposeBag.h
KDSDisposeBag.m
运行一下代码
正常打印
正常销毁
四、总结与思考
其实这里面并没有体现 KDSDisposeBag 的真正意义,因为 tableView 被添加到父视图上后引用计数就被 +1,所以,生命周期与当前控制器是一致的,那么,如果换成其他类型的对象,即使是临时创建的变量,那么 DisposeBag 的意义就是保有这些代码执行过程中创建的所有临时变量直到控制器生命结束。
而且,RxSwift 或者 RAC,它们的目的是让冗杂的代码下沉,暴露给外界的就是序列衔接命令,但是其内部的实现还是比较复杂的,所以,不必去困惑为啥写了很多代码其实就是本身一句话能解决的事
文章也仅为个人思考,代码拙劣,大神勿笑