倒计时是现在项目中很常用到的一个模块, 尤其是在跟电商项目挂钩的项目中.
之前在使用NSTimer时发现
如果NSTimer执行过程中由于某种原因被延迟,会略过本该在延迟期间需要执行的方法。
解决方案是使用GCD定时器。
/**
* 倒计时工具
*
* @param time 倒计时时间
* @param blockYes 倒计时结束 设置UI
* @param blockNo 倒计时进行中 设置UI
*/
+ (void)verificationCode:(long long)time blockYes:(void(^)())blockYes blockNo:(void(^)(id time))blockNo
{
__block long long timeout = time; //倒计时时间
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
dispatch_source_set_event_handler(_timer, ^{
if(timeout<=0){ //倒计时结束,关闭
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
//设置界面的按钮显示 根据自己需求设置
blockYes();
});
}else{
// int minutes = timeout / 60;
int seconds = timeout % 60;
NSString *strTime = [NSString stringWithFormat:@"%.2d", seconds];
dispatch_async(dispatch_get_main_queue(), ^{
//设置界面的按钮显示 根据自己需求设置
blockNo(strTime);
});
timeout--;
}
});
dispatch_resume(_timer);
}
这样写的话能够保证倒计时时间更准确.
既然是倒计时抢购, 光有倒计时是不够的. 还需要有剩余时间的显示, 你所得到的是秒数, 还需要把秒数转化为()天()时()分()秒.
- (void)getDetailTimeWithTimestamp:(NSInteger)timestamp
{
NSInteger ms = timestamp;
NSInteger ss = 1;
NSInteger mi = ss * 60;
NSInteger hh = mi * 60;
NSInteger dd = hh * 24;
// 剩余的
NSInteger day = ms / dd;// 天
NSInteger hour = (ms - day * dd) / hh;// 时
NSInteger minute = (ms - day * dd - hour * hh) / mi;// 分
NSInteger second = (ms - day * dd - hour * hh - minute * mi) / ss;// 秒
NSLog(@"%zd日:%zd时:%zd分:%zd秒",day,hour,minute,second);
self.limitTimeLabel.text = [NSString stringWithFormat:@"%zd天%zd:%zd:%zd",day,hour,minute,second];
}
这样, 一个倒计时抢购就完成了.
Log还是比较准的.