cell上添加倒计时,以及时差问题的解决
原址 http://www.cnblogs.com/zhangmaliang/p/5102518.html
最近项目中用到了tableView的多个cell倒计时系统问题,本觉得很简单的一个事,一做发现还没这么简单,就此记录。
下面方法模拟网络请求返回数据。

按照常规思路,根据网络请求返回remainTime,封装模型,存到数组中,再在表格代理方法中赋值给cell

cell中根据传入模型中的remainTime属性,开启定时器每隔1s调用如下方法

程序一运行发现问题:每当表格滚动时,表格代理方法cellForRowAtIndexPath会不断重复调用,从数组中取得模型赋值给cell,而模型中的remainTime是固定的,于是倒计时系统不断重复开始倒计时。
发现问题点,开始着手解决。开始想到的是方法是在控制器中也开启一套定时器系统,当服务器数据remainTime返回时,将其中remainTime大于0s的数据保存在一个字典中,对所有键值对开始倒计时。
下面方法模拟网络数据返回,对所有remainTime大于0的字段保存到字典self.timerDic中


cell属性model中的remainTime字段从这个一直变化的self.timerDic字典中取值,于是滚动视图时cell获取到的就不是一个固定的remainTime,效果如下

此时已经解决了表格滚动时倒计时重复计时问题,但可以看到多次滚动后会造成如上显示错误,这是由于控制器和cell两套定时系统时差而引起的,具体后面分析。
此路貌似不通,于是我想到了KVO,让cell监听控制器中remainTime的数值变化

仔细分析上面倒计时时差原因,发现时差产生是由于定时器调用频率导致。举个场景说明:控制器返回数据时remainTime是10,过了0.9999s后用户滚动表格,此时cell从字典self.timerDic中取到的remainTime仍旧是10,于是cell定时系统的remainTime值比控制器的慢了0.9999s。同理分析也可能快0.9999s,于是可能会引发最多2s的极限误差。
找到具体原因修改就比较容易了,使用CADisplayLink,一分钟调用60次countDown方法,每次减去1/60s,则最大误差只有2*1/60s,比较准确,能够满足要求

最后做下适当优化:定时器在主线程工作,调用频率很高,每次调用还要遍历字典对每一个value递减后覆盖旧值,故希望定时器能在后台工作。定时器工作在后台线程时会自动将其注册到后台线程的runloop,而runloop依托线程但并不会自动创建,此时countDown无法接收到事件回调,需要手动生成runloop并保证其不会退出。这里参照AFN中的生成方法,核心代码如下:

cell上添加倒计时,以及时差问题的解决的更多相关文章
- iOS tableview自定义cell上添加按钮实现删除功能
在删除的时候,先删除数据源,再删除cell 但是,会发现一直崩: numberOfRowsInSection 解决方案:
- iOS: 获取UITableViewCell上添加的子控件对应的cell
一.简单介绍 UITableViewCell是UITableView的核心部分,我们在开发中因为功能的扩展经常需要自定义,以便在其上面添加子控件,例如button.label等.添加后获取这些子控件的 ...
- ios 添加到cell 上的button点击无效!扩大button的点击区域(黑魔法)
一般情况下点击效果都是正常的!要不然你对它做了什么?一般细心的小伙伴都没有遇到这种情况,但是呢! 当然我是二班的!在这里我主要讲两个问题,解决问题和普及魔法. 一.普及问题(button在cell上点 ...
- iOS 在cell中使用倒计时的处理方法(新)
一.前言 之前的文章iOS 在cell中使用倒计时的处理方法得到大量的支持, 在这先感谢大家的支持. 但是也收到不少人的回复表示不会用, 需要一一解答, 由于之前写的时候没有使用Markdown编辑, ...
- iOS 在tableView上添加button导致按钮没有点击效果和不能滑动的 zhuang
转载请注明出处. 今天在调试代码的时候,在tableviewcell上添加button,发现button快速点击的话,是看不出点击效果的,查找资料发现, ios7上UITableViewCell子层容 ...
- iOS回顾笔记(09) -- Cell的添加、删除、更新、批量操作
iOS回顾笔记(09) -- Cell的添加.删除.更新.批量操作 项目中经常有对UITableViewCell做各种操作的需求: 添加一个新的cell 删除某行cell 刷新cell上某行数据(如修 ...
- iOS实现类似QQ的好友列表,自由展开折叠(在原来TableView的基础上添加一个字典,一个Button)
//直接代码 只包含 折叠展开字典的处理搭建#import "CFViewController.h" @interface CFViewController ()<UITab ...
- iOS:在cell中使用倒计时的最佳方法
一.简单介绍 在UITableViewCell中每条数据中显示该内容的倒计时, 并随时间进行倒数,这是很多电商app最常见的活动推销功能模块,自然想到用的就是计时器了. 二.基本想法 想法1:在每个c ...
- cell上的按钮点击和左滑冲突
cell上的某个按钮的点击事件,当cell左滑的时候,只要活动的区域也在按钮上,那么按钮的点击事件也会调用. fix: 给按钮添加一个手势(TapGesture)那么当点击的时候就会响应点击手势的方法 ...
随机推荐
- python3学习笔记(3)
一.内置函数补充1.callable()检测传递的参数是否可以被调用.def f1() pass可以被调用f2 = 123不可以被调用2.chr()和ord()chr()将ascii码转换成字符,or ...
- spring各个版本开发包下载
spring各个开发包版本下载地址:https://repo.spring.io/webapp/#/artifacts/browse/tree/General/libs-release-local/o ...
- Vim常用操作-合并行。
刚接触 Vim 会觉得它的学习曲线非常陡峭,要记住很多命令.所以这个系列的分享,不会教你怎么配置它,而是教你怎么快速的使用它. 在开发时为了代码美观,经常会把属性用换行的方式显示. <el-di ...
- AIO5系统中-打印样式常见问题处理
1.为什么我的报表没有数据显示? 答:请看一下报表是否有绑定数据源,有添加查询,如果这些都做了,请看下主项数据的数据源有没有绑定,这些都绑定了,就会有数据的显示. 2.为什么我做的报表分组很乱? 答: ...
- 安卓自定义控件(五)触控基础MotionEvent
之前去面试,人家说,我这个事件拦截机制写得太少了,还有一个MotionEvent没写,这个确实也很重要,后来我考虑了一下,决定将这篇文章放到自己定义控件里. 先简单再提一下事件分发,事件分发和拦截主要 ...
- python网络编程之单线程之间的并发
单线程之间的并发就是利用一个线程实现并发的效果,也就是利用了cup遇到阻塞的那段时间去做别的事情,从而提高了cup的利用率,使之在单个线程中就实现了并发的效果. 下面就是一个简单的服务端单个线程实现并 ...
- Bootstrap 开关(switch)使用整理
1.在JS里根据指定的 1或者0 或者其它值让按钮变成 on 或者 off (通常需要根据数据库查询的结果初始化开关的状态) (--开关插件包 bootstrap-switch.min.js) < ...
- TCP/IP协议栈 -----链路层
这节说一下链路层和ARP RARP协议 链路层: 在协议栈中链路层的目的有三个:1. 为IP模块发送或接受数据包 2.为ARP模块发送或接受ARP请求 3. 为RARP模块发送或接受RARP请求. 让 ...
- eclipse 常用插件 整理
开发过程中的常用Eclipse插件,按字母排序: (1) AmaterasUML 介绍:Eclipse的UML插件,支持UML活动图,class图,sequence图,usecas ...
- java 接口测试,使用excel做数据驱动(二)
承接上篇. 改变我们的测试驱动方式,灵活设置测试用例. 数据驱动测试 数据驱动测试的核心是: 测试数据与测试脚本分离,实现测试脚本参数化, 提高测试脚本的可重用性.在自动化功能测试中如果灵活使用数据源 ...