一.前言

之前的文章iOS 在cell中使用倒计时的处理方法得到大量的支持, 在这先感谢大家的支持. 但是也收到不少人的回复表示不会用, 需要一一解答, 由于之前写的时候没有使用Markdown编辑, 所以现在没法更新之前的文章, 重新写一份清晰的文章

需求: 每条Cell中显示倒计时, 并随时间进行倒数
语言: Objective-C & Swift
系统: iOS
Github地址: OYCountDownManager v2.0
OYCountDownManager-Swift v2.0

二.原理分析

 
原理分析图.png
 
单个列表倒计时.gif

v2.0新增

* 多个列表倒计时
* 多个页面倒计时
* 分页列表倒计时
* 后台模式倒计时
 
多个列表倒计时.gif
 
多个页面倒计时.gif
 
分页列表倒计时.gif

三.使用方法

1.1 第一种方法: 使用cocoapods自动安装

pod 'OYCountDownManager'

1.2 第二种方法

下载示例Demo, 把里面的OYCountDownManager文件夹拖到你的项目中

2. 在第一次使用的地方调用[kCountDownManager start]

- (void)viewDidLoad {
[super viewDidLoad]; // 启动倒计时管理
[kCountDownManager start];
}

3. 在Cell初始化中监听通知 kCountDownNotification

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 监听通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(countDownNotification) name:kCountDownNotification object:nil];
}
return self;
}

4. 在cell设置通知回调, 取得时间差, 根据时间差进行处理

- (void)countDownNotification {
/// 计算倒计时
NSInteger countDown = [self.model.count integerValue] - kCountDownManager.timeInterval;
if (countDown <= ) {
// 倒计时结束时回调
xxxx(使用代理或block)
}return;
/// 重新赋值
self.timeLabel.text = [NSString stringWithFormat:@"倒计时%02zd:%02zd:%02zd", countDown/, (countDown/)%, countDown%];
}

5. 当刷新数据时,调用reload方法

- (void)reloadData {
// 网络加载数据 // 调用[kCountDownManager reload]
[kCountDownManager reload];
// 刷新
[self.tableView reloadData];
}

6. 当不需要倒计时时, 废除定时器

[kCountDownManager invalidate];

四.高级使用(多列表.多页面.分页列表)

增加identifier:标识符, 一个identifier支持一个倒计时源, 有一个单独的时间差

/** 添加倒计时源 */
- (void)addSourceWithIdentifier:(NSString *)identifier; /** 获取时间差 */
- (NSInteger)timeIntervalWithIdentifier:(NSString *)identifier; /** 刷新倒计时源 */
- (void)reloadSourceWithIdentifier:(NSString *)identifier; /** 刷新所有倒计时源 */
- (void)reloadAllSource; /** 清除倒计时源 */
- (void)removeSourceWithIdentifier:(NSString *)identifier; /** 清除所有倒计时源 */
- (void)removeAllSource;

以一个页面有两个独立的列表为例

1.定义identifier(常量)

NSString *const OYMultipleTableSource1 = @"OYMultipleTableSource1";
NSString *const OYMultipleTableSource2 = @"OYMultipleTableSource2";

2.增加倒计时源

// 增加倒计时源
[kCountDownManager addSourceWithIdentifier:OYMultipleTableSource1];
[kCountDownManager addSourceWithIdentifier:OYMultipleTableSource2];

3.在cell通知回调中, 通过identifier取得时间差, 根据时间差进行处理

- (void)countDownNotification {
/// 判断是否需要倒计时 -- 可能有的cell不需要倒计时,根据真实需求来进行判断
if () {
return;
}
/// 计算倒计时
OYModel *model = self.model;
/// 根据identifier取得时间差, 以OYMultipleTableSource1为例
NSInteger timeInterval = timeInterval = [kCountDownManager timeIntervalWithIdentifier: OYMultipleTableSource1];
}
NSInteger countDown = model.count - timeInterval;
/// 当倒计时到了进行回调
if (countDown <= ) {
self.detailTextLabel.text = @"活动开始";
// 倒计时结束时回调
xxxx(使用代理或block)
return;
}
/// 重新赋值
self.detailTextLabel.text = [NSString stringWithFormat:@"倒计时%02zd:%02zd:%02zd", countDown/, (countDown/)%, countDown%];
}

4. 当刷新数据时,调用reloadSourceWithIdentifier:刷新时间差

- (void)reloadData {
// 网络加载数据 // 调用reloadSourceWithIdentifier:刷新时间差
[kCountDownManager reloadSourceWithIdentifier:OYMultiplePageSource1];
// 刷新
[self.tableView reloadData];
}

5. 当页面销毁, 移除倒计时源, 或者不需要定时器, 废除定时器

- (void)reloadData {
// 网络加载数据 // 调用reloadSourceWithIdentifier:刷新时间差
[kCountDownManager reloadSourceWithIdentifier:OYMultiplePageSource1];
// 刷新
[self.tableView reloadData];
}

五.注意事项

误差分析

  • NSTimer可以精确到50-100毫秒,不是绝对准确的,所以使用时间累加的方法时间久了有可能成为时间误差的来源
  • 为秒为单位触发定时器, 当reloadData后, 定时器也许刚好到达触发点, 时间差+1, 数据刚reload完就马上-1秒
  • 后台模式是以进入后台的本地时间, 及进入前台的本地时间做差值来计算的, 当用户手动修改本地时间, 也会成为时间差错误的来源之一, 如果能在进入前台的时间再从服务器取一次数据, 或者记录服务器时间而不是本地时间, 也可以避免这一误差

滚动cell时出去文字闪烁

在给cell的模型赋值后, 最好手动调用一下countDownNotification方法, 保证及时刷新

///  重写setter方法
- (void)setModel:(Model *)model {
_model = model;
self.titleLabel.text = model.title;
// 手动调用通知的回调
[self countDownNotification];
}

倒计时为0后出现复用问题

在倒计时为0后, 应该回调给控制器, 从后台请求一次数据, 保证倒计时没有出现误差

if (countDown <= ) {
// 倒计时结束时回调
xxxx(使用代理或block)
}return;

出现每秒倒计时减2的问题

1.查看定时器设置是否正确, 或者通知是否监听了两次
2.在countDownNotification方法中, 是否用[NSDate date]做了某些计算, 因为[NSDate date]为当前时间, 每一秒去取都会比上一秒大一秒, 再加上timeInterval也是一秒加一, 那么就会出现每秒倒计时减2的问题

如果还有不懂的问题, 或者出现其它bug
请查看Demo: Demo
或者给我留言, 喜欢的话, 就给作者一个star

作者:大头herob
链接:https://www.jianshu.com/p/af62a56ef7e2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 
 
 

iOS 在cell中使用倒计时的处理方法(新)的更多相关文章

  1. iOS:在cell中使用倒计时的最佳方法

    一.简单介绍 在UITableViewCell中每条数据中显示该内容的倒计时, 并随时间进行倒数,这是很多电商app最常见的活动推销功能模块,自然想到用的就是计时器了. 二.基本想法 想法1:在每个c ...

  2. iOS去掉字符串中的HTML标签的方法

    方法一.NSScanner去除标签 - (NSString *)removeTheHtmlFromString:(NSString *)htmlString { NSScanner * scanner ...

  3. iOS 之项目中遇到的问题总结

    昨天去一家公司面试,面试官问了我在项目开发中遇到过哪些问题,是什么引起的,怎样解决的? 当时由于有点小紧张只说出了一两点,现在就来好好总结一下. 问题: 1.两表联动 所谓的两表联动就是有左右两个表格 ...

  4. [每天记录一个Bug]Cell中由于block加载网络请求产生的复用

    Bug 出现场景:   cell中使用加载图片的网络请求出现复用,截图如下:         复用原因:   Cell Model中只有一个用户的uid,所有用户相关信息:例如头像\名称\信息等是通过 ...

  5. iOS UIAlertController中加入倒计时,输入框,Swift讲解

    一.倒计时 @interface ViewController () { UIAlertController *alertview; NSString * message; NSTimer * wai ...

  6. iOS学习——tableview中带编辑功能的cell键盘弹出遮挡和收起问题解决

    最近在项目中经常用到UITableView中的cell中带有UITextField或UITextView的情况,然后在这种场景下,当我们点击屏幕较下方的cell进行编辑时,这时候键盘弹出来会出现遮挡待 ...

  7. iOS中获取cell中webview的内容尺寸

    最近项目中遇到在cell中获取webView的内容的尺寸的需求 实现的思路其实很简单 就是通过执行js 获取尺寸即可 为了后面用着方便我直接封装了一个HTML的cell 起名就叫 STHTMLBase ...

  8. iOS之UITableView中的cell因为重用机制导致新的cell的数据出现重复或者错乱

      UITableView中的cell可以有很多,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,当cell滚 ...

  9. iOS:一个Cell中设置另外一个Cell中的button

    场景: 子类化Cell中有button,拥有选中式样,点击第一个Cell中的button后,Cell一中的button获得选中式样.可是当点击Cell二中的button时.Cell一中的button选 ...

随机推荐

  1. Java集合框架:Collections工具类

    java.util.Collections工具类提供非常多实用的方法.使得程序员操作集合类的时候更加的方便easy,这些方法都是静态的. 整个Collections工具类源代码几乎相同有4000行.我 ...

  2. hdu 5078

    Osu! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Sub ...

  3. (转)javascript日期格式化扩展

    转自:http://blog.csdn.net/vbangle/article/details/5643091 javascript Date format(js日期格式化)   方法一:这个很不错, ...

  4. MySQL服务停止,无法启动了~

    怎么解决mysql服务无法启动的问题

  5. memcache的内存管理机制

    Memcache使用了Slab Allocator的内存分配机制:按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题Memcache的存储涉及到slab,page,chunk三 ...

  6. 《转》Win7 IIS7.5 安装

    一.进入Win7的 控制面板,选择左侧的 打开或关闭Windows功能. 二.现在出现了安装Windows功能的选项菜单,注意选择的项目,我们需要手动选择需要的功能,下面这张图片把需要安装的服务都已经 ...

  7. Powershell ——findstr

    从文件中找出关键字 $colItems = Get-ChildItem d:\test #定义文件夹的路径 foreach ($i in $colItems) #循环获取文件夹下的txt文件 { $f ...

  8. protoc-gen-go: error:bad Go source code was generated: 163:6: illegal UTF-8 encoding (and 2915 more errors)

    protoc-gen-go: error:bad Go source code was generated: 163:6: illegal UTF-8 encoding (and 2915 more ...

  9. pip与apt-get

    在ubuntu服务器下安装包的时候,经常会用到sudo apt-get install 包名 或 sudo pip install 包名,那么两者有什么区别呢? 1.区别 pip用来安装来自PyPI( ...

  10. screenX clientX pageX区别

    screenX:鼠标位置相对于用户屏幕水平偏移量,而screenY也就是垂直方向的,此时的参照点也就是原点是屏幕的左上角. clientX:跟screenX相比就是将参照点改成了浏览器内容区域的左上角 ...