iOS实现毫秒倒计时的方法详解
程序员文章站
2023-12-19 23:59:16
前言
大家应该都知道在app开发中,当展示限时优惠的某些商品时,往往会加一个倒计时,提示用户该商品限时优惠所剩的时间,。那对于开发者来说,这就需要我们去实现的是一个倒计时...
前言
大家应该都知道在app开发中,当展示限时优惠的某些商品时,往往会加一个倒计时,提示用户该商品限时优惠所剩的时间,。那对于开发者来说,这就需要我们去实现的是一个倒计时的功能,这个倒计时根据具体需求,可以以天、小时、分、秒、毫秒作单位。
今天呢,主要说说毫秒计时器。我们知道秒和毫秒之间的进制是1000,也就是说1秒=1000毫秒,那我们做毫秒倒计时器的时候是设置一个时间间隔为1毫秒的计时器,逐一减少毫秒数。但是这样的话太耗时了,所以很多的毫秒计时器中的毫秒数只是0-9之间的数字,这就意味着,这个毫秒计时器的时间间隔是100毫秒,这样相比起1毫秒为间隔的计时器,其消耗就少了很多,同时也达到毫秒计时的效果。
那对于整个毫秒倒计时的实现思路就是:得到未来某个日期的时间戳和当前日期的时间戳,计算这两者之间的时间差,然后设置一个时间间隔为100毫秒的计时器,每隔100毫秒,更新一下倒计时器上相应的数值。
实现方法
自定义一个uiview,将倒计时封装起来。
一、在mseccountdownview.h中增加时间戳和计时器这两属性
@interface mseccountdownview : uiview @property(nonatomic, assign)double timeinterval;//未来某个日期的时间戳 @property(nonatomic, strong)nstimer *timer ; //定时器 @end
二、在mseccountdownview.m实现相关ui及倒计时方法
@interface mseccountdownview (){ uiview *countdownbackview; cgfloat _passtime; } @property(nonatomic, strong)uilabel *tiplabel; @property(nonatomic, strong)uilabel *hourslabel; @property(nonatomic, strong)uilabel *minuteslabel; @property(nonatomic, strong)uilabel *secondslabel; @property(nonatomic, strong)uilabel *millionsecondslabel; @property(nonatomic, strong)uilabel *label1; @property(nonatomic, strong)uilabel *label2; @property(nonatomic, strong)uilabel *label3; @property(nonatomic, strong)uilabel *label4; @end
创建相关ui
- (instancetype)initwithframe:(cgrect)frame { self = [super initwithframe:frame]; if (self) { countdownbackview=[[uiview alloc] initwithframe:cgrectmake(0, 0, self.frame.size.width, self.frame.size.height)]; [self addsubview:countdownbackview]; _tiplabel=[[uilabel alloc] init]; _tiplabel.frame = cgrectmake(0, 0, 40, countdownbackview.frame.size.height); [countdownbackview addsubview:_tiplabel]; _tiplabel.font = [uifont systemfontofsize:12]; //小时 _hourslabel=[[uilabel alloc] initwithframe:cgrectmake(_tiplabel.frame.origin.x+_tiplabel.frame.size.width, 0, 35, countdownbackview.frame.size.height)]; [countdownbackview addsubview:_hourslabel]; _hourslabel.font = [uifont systemfontofsize:11]; _label1=[[uilabel alloc] initwithframe:cgrectmake(_hourslabel.frame.origin.x+_hourslabel.frame.size.width, _hourslabel.frame.origin.y, 8, countdownbackview.frame.size.height)]; [countdownbackview addsubview:_label1]; //分钟 _minuteslabel=[[uilabel alloc] initwithframe:cgrectmake(_label1.frame.origin.x+_label1.frame.size.width, _hourslabel.frame.origin.y, 20, countdownbackview.frame.size.height)]; [countdownbackview addsubview:_minuteslabel]; _minuteslabel.font = [uifont systemfontofsize:11]; _label2=[[uilabel alloc] initwithframe:cgrectmake(_minuteslabel.frame.origin.x+_minuteslabel.frame.size.width, _hourslabel.frame.origin.y, 8, countdownbackview.frame.size.height)]; [countdownbackview addsubview:_label2]; //秒 _secondslabel=[[uilabel alloc] initwithframe:cgrectmake(_label2.frame.origin.x+_label2.frame.size.width, _hourslabel.frame.origin.y, 20 , countdownbackview.frame.size.height)]; [countdownbackview addsubview:_secondslabel]; _secondslabel.font = [uifont systemfontofsize:11]; _label3=[[uilabel alloc] initwithframe:cgrectmake(_secondslabel.frame.origin.x+_secondslabel.frame.size.width, _hourslabel.frame.origin.y, 8 , countdownbackview.frame.size.height)]; [countdownbackview addsubview:_label3]; _millionsecondslabel=[[uilabel alloc] initwithframe:cgrectmake(_label3.frame.origin.x+_label3.frame.size.width, _hourslabel.frame.origin.y, 20, countdownbackview.frame.size.height)]; [countdownbackview addsubview:_millionsecondslabel]; //毫秒 _millionsecondslabel.font = [uifont systemfontofsize:11]; _label1.textalignment=1; _label2.textalignment=1; _label3.textalignment = 1; _hourslabel.textalignment=1; _minuteslabel.textalignment=1; _secondslabel.textalignment=1; _millionsecondslabel.textalignment=1; _passtime=0.0; } return self; }
生成一个计时器
//得到未来某个日期的时间戳,与当前时间戳相比,得到两者的时间差,生成定时器 - (void)settimeinterval:(double)timeinterval { _timeinterval = timeinterval ; nsdateformatter *dataformatter = [[nsdateformatter alloc] init]; dataformatter.dateformat = @"mm/dd/yyyy hh:mm:ss.sss"; //获取当前系统的时间,并用相应的格式转换 [dataformatter stringfromdate:[nsdate date]]; nsstring *currentdaystr = [dataformatter stringfromdate:[nsdate date]]; nsdate *currentdate = [dataformatter datefromstring:currentdaystr]; //优惠结束的时间,也用相同的格式去转换 nsdate *date = [nsdate datewithtimeintervalsince1970:timeinterval/1000.0]; nsstring *deadlinestr = [dataformatter stringfromdate:date]; nsdate *deadlinedate = [dataformatter datefromstring:deadlinestr]; _timeinterval=[deadlinedate timeintervalsincedate:currentdate]*1000; if (_timeinterval!=0) { //时间间隔是100毫秒,也就是0.1秒 _timer = [nstimer scheduledtimerwithtimeinterval:0.1f target:self selector:@selector(timeraction) userinfo:nil repeats:yes]; [[nsrunloop currentrunloop] addtimer:_timer formode:uitrackingrunloopmode]; }else{ [countdownbackview removefromsuperview]; } }
实现每隔100毫秒执行的方法,更新倒计时器上面相应的数值
// 每间隔100毫秒定时器触发执行该方法 - (void)timeraction { [self gettimefromtimeinterval:_timeinterval] ; // 当时间间隔为0时干掉定时器 if (_timeinterval-_passtime == 0) { [_timer invalidate] ; _timer = nil ; } } // 通过时间间隔计算具体时间(小时,分,秒,毫秒) - (void)gettimefromtimeinterval : (double)timeinterval { //1s=1000毫秒 _passtime += 100.f;//毫秒数从0-9,所以每次过去100毫秒 _tiplabel.text=@"还剩:"; _label3.text=@"."; _label2.text=@":"; _label1.text=@":"; //小时数 nsstring *hours = [nsstring stringwithformat:@"%ld", (nsinteger)((timeinterval-_passtime)/1000/60/60)]; //分钟数 nsstring *minute = [nsstring stringwithformat:@"%ld", (nsinteger)((timeinterval-_passtime)/1000/60)%60]; //秒数 nsstring *second = [nsstring stringwithformat:@"%ld", ((nsinteger)(timeinterval-_passtime))/1000%60]; //毫秒数 cgfloat sss = ((nsinteger)((timeinterval - _passtime)))%1000/100; nsstring *ss = [nsstring stringwithformat:@"%.lf", sss]; if (minute.integervalue < 10) { minute = [nsstring stringwithformat:@"0%@", minute]; } self.hourslabel.text = [nsstring stringwithformat:@"%@",hours]; self.minuteslabel.text = [nsstring stringwithformat:@"%@",minute]; self.secondslabel.text = [nsstring stringwithformat:@"%@",second]; self.millionsecondslabel.text = [nsstring stringwithformat:@"%@",ss]; if (timeinterval - _passtime <= 0) { [countdownbackview removefromsuperview]; [self removefromsuperview]; } }
三、在viewcontroller.m给倒计时器赋值,实现自己想要的倒计时
- (void)viewdidload { [super viewdidload]; msecview=[[mseccountdownview alloc] initwithframe:cgrectmake(50, 100, self.view.frame.size.width-100, 16)]; [self.view addsubview:msecview]; nsdateformatter *formatter = [[nsdateformatter alloc] init]; [formatter setdatestyle:nsdateformattermediumstyle]; [formatter settimestyle:nsdateformattershortstyle]; [formatter setdateformat:@"yyyy-mm-dd hh:mm:ss.sss"]; nsdate* date = [formatter datefromstring:@"2017-04-11 15:10:00.000"]; //将日期转换成时间戳 nsinteger timesp = [[nsnumber numberwithdouble:[date timeintervalsince1970]] integervalue]*1000; msecview.timeinterval=timesp; }
这样就实现倒计时的功能了。但是使用倒计时还需要注意一点,当离开该页面的时候,记得把定时器暂停,等回到该页面的时候再启动倒计时。
这个可以通过以下两方法实现。
-(void)viewwillappear:(bool)animated{ // 页面出现时,开启计时器 [msecview.timer setfiredate:[nsdate distantpast]]; } -(void)viewwilldisappear:(bool)animated{ // 页面消失时,暂停提示器 [msecview.timer setfiredate:[nsdate distantfuture]]; }
如有需要,可通过下面两种方法下载demo
二:本地下载
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。