iOS在cell中使用倒计时的处理方法, 全局使用一个NSTimer对象
OC版本: OYCountDownManager-OC
- 单个列表倒计时
- 多个列表倒计时
- 多个页面倒计时
- 分页列表倒计时
- 后台模式倒计时
pod 'OYCountDownManager_swift'
下载示例Demo, 把里面的OYCountDownManager文件夹拖到你的项目中
override func viewDidLoad() {
super.viewDidLoad()
// 启动倒计时管理
OYCountDownManager.sharedManager.start()
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .value1, reuseIdentifier: reuseIdentifier)
NotificationCenter.default.addObserver(self, selector: #selector(self.countDownNotification), name: OYCountDownNotification, object: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
NotificationCenter.default.addObserver(self, selector: #selector(self.countDownNotification), name: OYCountDownNotification, object: nil)
}
@objc private func countDownNotification() {
// 计算倒计时
let countDown = self.model?.count - OYCountDownManager.sharedManager.timeInterval
if countDown <= 0 {
// 倒计时结束时回调
xxxx(使用代理或block)
return;
}
// 重新赋值
self.detailTextLabel?.text = String(format: "%02d:%02d:%02d", countDown/3600, (countDown/60)%60, countDown%60)
}
@objc private func reloadData() -> Void {
// 网络加载数据
// 调用reload()
OYCountDownManager.sharedManager.reload()
// 刷新
self.tableView.reloadData()
}
OYCountDownManager.sharedManager.invalidate()
增加identifier:标识符, 一个identifier支持一个倒计时源, 有一个单独的时间差
/** 添加倒计时源 */
public func addSourceWithIdentifier(identifier: String) -> Void
/** 获取时间差 */
public func timeIntervalWithIdentifier(identifier: String) -> Int
/** 刷新倒计时源 */
public func reloadSourceWithIdentifier(identifier: String) -> Void
/** 刷新所有倒计时源 */
public func reloadAllSource() -> Void
/** 清除倒计时源 */
public func removeSourceWithIdentifier(identyfier: String) -> Void
/** 清除所有倒计时源 */
public func removeAllSource() -> Void
以一个页面有两个独立的列表为例
let OYMultipleTableSource1 = "OYMultipleTableSource1"
let OYMultipleTableSource2 = "OYMultipleTableSource2"
// 增加倒计时源
OYCountDownManager.sharedManager.addSourceWithIdentifier(identifier: OYMultipleTableSource1)
OYCountDownManager.sharedManager.addSourceWithIdentifier(identifier: OYMultipleTableSource2)
@objc private func countDownNotification() {
// 判断是否需要倒计时 -- 可能有的cell不需要倒计时,根据真实需求来进行判断
if false {
return
}
// 计算倒计时
let model = self.model!
// 根据identifier取得时间差, 以OYMultipleTableSource1为例
let timeInterval = OYCountDownManager.sharedManager.timeIntervalWithIdentifier(identifier: model.countDownSource!)
let countDown = model.count - timeInterval
if countDown <= 0 {
// 倒计时结束时回调
xxxx(使用代理或block)
return;
}
// 重新赋值
self.detailTextLabel?.text = String(format: "%02d:%02d:%02d", countDown/3600, (countDown/60)%60, countDown%60)
}
private func reloadData() -> Void {
// 网络加载数据
// 调用reloadSourceWithIdentifier(identifier)刷新时间差
OYCountDownManager.sharedManager.reloadSourceWithIdentifier(identifier: OYMultipleTableSource1)
// 刷新
self.tableView.reloadData()
}
// 移除所有倒计时源
OYCountDownManager.sharedManager.removeAllSource()
// 废除定时器
OYCountDownManager.sharedManager.invalidate()
- NSTimer可以精确到50-100毫秒,不是绝对准确的,所以你使用时间累加的方法时间久了有可能成为时间误差的来源
- 以秒为单位触发定时器, 当reloadData后, 定时器也许刚好到达触发点, 时间差+1, 数据刚reload完就马上-1秒
- 后台模式是以进入后台的绝对时间, 及进入前台的绝对时间做差值来计算的, 差值会进行取整, 导致一点点误差
在给cell的模型赋值后, 最好手动调用一下countDownNotification方法, 保证及时刷新
var model: OYModel? {
didSet {
self.textLabel?.text = model!.title
self.countDownNotification()
}
}
在倒计时为0后, 应该回调给控制器, 从后台请求一次数据, 保证倒计时没有出现误差
if (countDown <= 0) {
// 倒计时结束时回调
xxxx(使用代理或block)
return
}
1.查看定时器设置是否正确, 或者通知是否监听了两次
2.在countDownNotification方法中, 是否用[NSDate date]做了某些计算, 因为[NSDate date]为当前时间, 每一秒去取都会比上一秒大一秒, 再加上timeInterval也是一秒加一, 那么就会出现每秒倒计时减2的问题
- 还有不懂的问题, 或者出现其它bug
- 请查看Demo: Demo
- 简书地址:http://www.jianshu.com/p/af62a56ef7e2
- 或者给我留言, 喜欢的话, 就给作者一个star