ReactiveCocoa|ReactiveCocoa (RAC) TableView(数据篇)

上一篇写了点简单的 KVO的数据绑定,刚了解这个特性的时候,我就想到了 利用到tableview上,感觉可以实现一种非常简单的绑定 model 和cell 的方式,但是经过实践 ,是会出现Bug的,再研究,然后解决掉这个Bug后,感觉对Cell的绑定 操作有点多,对cell展示的流畅性 感觉会产生阻碍,所以又放弃了这种方式,特别简单的Cell还是可以用的,下面让我们来 一起探讨下吧
承接上篇

[RACObserve(model, title) subscribeNext:^(NSString *x) { self.textLabel.text = x; }];

我们经常会有改变cell对应的Model的属性,然后要更新到Cell上的,一般我的做法是 改变Model的属性后,
1.找到Model对应的cell 2.刷新 Model对应的Cell

应该会有一大部分人都是这样做的,如果有更好的办法请评论联系我,回归正题,结合 RAC 我们可以把 Model的属性和 Cell的subviews(label imageView等)绑定在一起,这样就只需要 改变Model的属性的值,就会自动调用 rac的block,cell.m里的代码如下
-(void)bindModel:(YFRACTestModel *)model { [RACObserve(model, title) subscribeNext:^(NSString *x) { self.textLabel.text = x; }]; [RACObserve(model, sex) subscribeNext:^(NSString *x) { self.detailTextLabel.text = x; }]; }

好像很方便呢,一口气写 10个列表好像都不费力了呢
我也高兴了好一阵子,觉得 春天到了,写程序也是一件不累人多拿钱的活呢,仔细一想 我的天哪,Bug已经悄无声息的渗透了进来,
让我们来 分析下,
bindModel: 这个方法是给Cell绑定数据用的, 由于Cell是复用的,所以同一个Cell可能 执行 好多次 bindModel: 方法, 也就意味着model的属性 和 cell的UI 会经过多次的绑定, 而且 新的Model的绑定并不会覆盖掉 旧的model的绑定, 这就导致了 cell 绑定了多个Model的属性, 改变任何一个Model的值,都会更新cell的显示,这显然不是我们想要的 我们写个tableView的Demo来验证下, 点击cell改变Model的值,看看哪个Cell会更新, 附上 点击cell的代码

if (indexPath.row - 10 < 0) { NSLog(@"请点击更下方的cell"); return; }YFRACTestModel *model = self.dataArray[indexPath.row - 10]; model.sex = @"00000";

【ReactiveCocoa|ReactiveCocoa (RAC) TableView(数据篇)】效果
ReactiveCocoa|ReactiveCocoa (RAC) TableView(数据篇)
文章图片
000000.gif 通过这张图,我们看到了 点击 当前cell改变相差10个下标的Model的值,相差1个下表的cell 更新了UI,这显然是一个bug了
Demo代码
https://pan.baidu.com/s/1o8NUh1S 提取码:v624
Bug出现,就该干掉,让我们 解决掉它
既然Bug是由于 多次绑定出现的,那我们就在新的绑定关系发生前,把旧的绑定关系除掉,经过调研,这确实是可行的,我们看下代码
cell.m 代码
#import "YFTestCell.h"#import @implementation YFTestCell { RACDisposable * _lastTitleSig; RACDisposable * _lastSexSig; }-(void)bindModel:(YFRACTestModel *)model { // 解除 上一个model的 绑定 [_lastTitleSig dispose]; [_lastSexSig dispose]; __weak typeof(self)weakS = self; RACDisposable * titleSig = [RACObserve(model, title) subscribeNext:^(NSString *x) { weakS.textLabel.text = x; }]; RACDisposable * sexSig = [RACObserve(model, sex) subscribeNext:^(NSString *x) { weakS.detailTextLabel.text = x; }]; // 记录 当前model的 绑定,下一次绑定时,先解除绑定 _lastTitleSig = titleSig; _lastSexSig = sexSig; } @end

重新运行我们的Demo,发现没有问题了,也达到了我们最初的想法,但是 感觉在cell 绑定数据时发生了太多的操作,RAC 的绑定和解除绑定也有一定的消耗CPU,如果cell过于复杂绑定太多的属性,对于cell的流畅性会有一定的影响,所以采用此方案时,要慎重呀
致此 ,本文 结束,期待大家的评论互动,如果帮到了你,请喜欢收藏下哦,下次见

    推荐阅读