近段的项目有个毫秒倒计时的需求,在网上找了好久,都没有找到明确的Demo或者毫秒倒计时的知识点,所以就借鉴了一些前辈的思路,和自己琢磨,然后成功把毫秒倒计时弄了出来。目前我知道的有两种做法,如下:
1.用一个定时器实现倒计时列表的毫秒倒计时
首先创建好定时器,如果不加入runloop中就会引发滑动表格时,倒计时停止的现象:
// 开启定时器
_timer = [NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
_passTime = 0.0f;
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:UITrackingRunLoopMode];
然后设置倒计时的时长,因为是列表的原因,所以就随机了20条以毫秒为单位的数据
_dataArray = [NSMutableArray arrayWithCapacity:0];
for (int i = 0; i < 20; i++) {
// 取秒为单位
[_dataArray addObject:@(rand() % 600*1000)];
}
最后取表格可见cell,并记录好已经pass的时间,定时刷新cell的倒计时内容,此处有个注意的地方就是时间转换的问题,如果用1毫秒来倒计时的话个人感觉太耗性能了,所以改为10毫秒,毫秒倒计时位数正好也是两位,刚好满足需求。
//定时器刷新倒计时
- (void)timerAction {
//取出屏幕可见cell
NSArray *cells = _countdowntable.visibleCells;
_passTime += 10.f;
for (UITableViewCell *cell in cells) {
NSIndexPath *indexPath = [_countdowntable indexPathForCell:cell];
NSInteger index = indexPath.row;
NSInteger remainTime = [_dataArray[index] integerValue];
if (remainTime - _passTime <= 0) {
cell.textLabel.text = @"00:00:00";
[_dataArray removeObjectAtIndex:index];
[_countdowntable deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
} else {
NSString *minute = [NSString stringWithFormat:@"%d", (int)((remainTime - _passTime)/1000/60)%60];
NSString *second = [NSString stringWithFormat:@"%d", ((int)(remainTime - _passTime))/1000%60];
CGFloat sss = ((int)((remainTime - _passTime)))%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
cell.textLabel.text = [NSString stringWithFormat:@"%@:%@:%@", minute, second, ss];
}
}
}
2.每个cell用一个定时器实现
这个跟第一个方法类似,但是它的定时器在cell里边创建,也就是说在不计算重用cell的情况,一个页面上有可能会同时存在N个定时器,比较耗性能,表示电脑在运行倒计时Demo的时候,风扇转的N快。
为了确保数据源也同步,传入数据源数组,然后每减少0.01s就替换一次数组中对应减少的值。
倒计时刷新的方法
- (void)countdownAction {
if (_remainTime <= 0) {
[self timerStop];
_countdown.text = @"此Cell倒计时完成";
} else {
_remainTime -= 10;
NSString *hour = [NSString stringWithFormat:@"%ld", _remainTime/1000/60/60];
NSString *minute = [NSString stringWithFormat:@"%ld", _remainTime/1000/60%60];
NSString *second = [NSString stringWithFormat:@"%ld", _remainTime/1000%60];
CGFloat sss = _remainTime%1000/10;
NSString *ss = [NSString stringWithFormat:@"%.lf", sss];
if (hour.integerValue && hour.integerValue < 10) {
hour = [NSString stringWithFormat:@"0%@", hour];
}
if (minute.integerValue < 10) {
minute = [NSString stringWithFormat:@"0%@", minute];
}
if (second.integerValue < 10) {
second = [NSString stringWithFormat:@"0%@", second];
}
if (ss.integerValue < 10) {
ss = [NSString stringWithFormat:@"0%@", ss];
}
_countdown.font = [UIFont systemFontOfSize:28];
if (hour.integerValue) {
_countdown.text = [NSString stringWithFormat:@"%@:%@:%@:%@", hour, minute, second, ss];
} else {
_countdown.text = [NSString stringWithFormat:@"%@:%@:%@", minute, second, ss];
}
}
}
然后在cell中定时器开启的用法也跟方法1一样,同样是添加到runloop中
if (!_timer && _remainTime > 0) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:@selector(countdownAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:UITrackingRunLoopMode];
}
差不多就这些了,github上面有Demo,希望能帮到你,如有更好的想法,欢迎留言...