美文网首页iOS常见功能demoiOS精华文章电商
iOS商城类商品抢购倒计时那点事

iOS商城类商品抢购倒计时那点事

作者: 夜的v | 来源:发表于2016-06-12 17:26 被阅读1405次

    一.之前电商项目做过的倒计时功能,笔记一下。
    主要有两种思路:①:根据当前系统时间和抢购结束时间计算差值,计算倒计时。 ②:后台返回当前时间距离抢购结束时间的总秒数。根据秒数本地倒计时。(第二种方案更为准确,不受本地时间误差的影响)

    代码如下:

    方案一:根据当前系统时间和抢购结束时间计算差值,计算倒计时。在cell的m文件中计算。但是系统时间可能有误差,导致计时准确性有待提高。
    1.cell的.h文件中定义属性字段@property(nonatomic,copy) NSString* endTime;
    2:cell的.m文件中重写endTime的set方法,传入结束日期。
    - (void)setEndTime:(NSString *)endTime 
    {
        _endTime  =endTime;
        NSTimer *time = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshTime:) userInfo:nil repeats:YES];
        [self refreshTime:time];
        [[NSRunLoop currentRunLoop] addTimer:time forMode:NSRunLoopCommonModes];
    }
    - (void)refreshTime:(NSTimer *)tm
    {
        NSDate *currentDate =[NSDate date];
        NSCalendar *calendar = [NSCalendar currentCalendar];
        
        NSCalendarUnit  unit = NSDayCalendarUnit | NSCalendarUnitHour | NSCalendarUnitMinute  | NSCalendarUnitSecond;
        NSDateComponents *commponent = [calendar components:unit fromDate:currentDate toDate:[HFTools getDateWithString:_endTime ] options:NSCalendarWrapComponents];
        
        NSDate *dt = [[HFTools getDateWithString:_endTime] earlierDate:currentDate];
        if([dt isEqualToDate:[HFTools getDateWithString:_endTime ]])
        {
            [tm invalidate];
            self.daoJiShiLabel.text = [NSString stringWithFormat:@"剩余0天 已结束"];
        }else
        {
            self.daoJiShiLabel.text = [NSString stringWithFormat:@"剩余%zd天 %02zd:%02zd:%02zd",commponent.day,commponent.hour,commponent.minute,commponent.second];    
        }
    }
    /******************
    //其中[HFTools getDateWithString:_endTime ]方法为:
    +(NSDate*)getDateWithString:(NSString *)time{
        NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];//实例化一个NSDateFormatter对象
         [dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//设定时间格式,这里可以设置成自己需要的格式 
        NSDate *date =[dateFormat dateFromString:time];
        return date;
    }
    

    方案二:

    **方案二:后台给出距离抢购结束的总秒数,根据总秒数,计算倒计时。(计时准确.)。
    
    
    ![countDownPic.gif](http:https://img.haomeiwen.com/i1486049/1d675936523b06f0.gif?imageMogr2/auto-orient/strip)
    
    代码:
    #pragma mark - - 倒计时Timer..
    - (void)initCountDown {
        for (NSInteger i = 0; i < self.dataArray.count; i++)
        {
            //将倒计时总秒数数组根据indexpath依次存入字典
            NSDictionary *CountDic = @{@"indexPath":[NSString stringWithFormat:@"%ld",i],@"lastTime": self.dataArray[i]};
            [self.countDownDataArray addObject:CountDic];
        }
        
        // 防止刷新界面的时候创建多个定时器,导致多个定时器一起倒计时。
        if (!self.MainTimer) {
            [self startTimer];
        }
    }
    
    //倒计时
    - (void)startTimer
    {
        self.MainTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshLessTime) userInfo:@"" repeats:YES];
        
        //如果不添加下面这条语句,在UITableView拖动的时候,会阻塞定时器的调用
        [[NSRunLoop currentRunLoop] addTimer:self.MainTimer forMode:UITrackingRunLoopMode];
    }
    
    //刷新时间
    - (void)refreshLessTime
    {
        NSUInteger time;
        for (int i = 0; i < self.countDownDataArray.count; i++) {
            time = [[[self.countDownDataArray objectAtIndex:i] objectForKey:@"lastTime"] integerValue];
            NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[[[self.countDownDataArray objectAtIndex:i] objectForKey:@"indexPath"] integerValue] inSection:0];
            NSInteger oldTime;
            if (time == 0) {
                oldTime = 0;
            }else {
                oldTime = --time;
            }
            NSString *str;
            str = [NSString stringWithFormat:@"%@",[self lessSecondToDay:oldTime]];
            
            //根据indexpath取cell
            YMCountDownCell *cell = (YMCountDownCell *)[self.tableView cellForRowAtIndexPath:indexPath];
            cell.countDownLabel.text = [self lessSecondToDay:oldTime];
            
            //将倒计时后的秒数存入数组,刷新数据源。
            NSDictionary *dic = @{@"indexPath": [NSString stringWithFormat:@"%ld",indexPath.row],@"lastTime": [NSString stringWithFormat:@"%ld",time]};
            [self.countDownDataArray replaceObjectAtIndex:i withObject:dic];
        }
    }
    
    //根据秒数计算剩余时间:天,小时,分钟,秒
    - (NSString *)lessSecondToDay:(NSUInteger)seconds
    {
        NSUInteger day  = (NSUInteger)seconds/(24*3600);
        NSUInteger hour = (NSUInteger)(seconds%(24*3600))/3600;
        NSUInteger min  = (NSUInteger)(seconds%(3600))/60;
        NSUInteger second = (NSUInteger)(seconds%60);
        NSString *timeStr;
        if (seconds == 0) {
            timeStr = @"已结束";
            [self countDownFinished];
        }else {
            timeStr = [NSString stringWithFormat:@"%02zd天 %02zd:%02zd:%02zd",(unsigned long)day,(unsigned long)hour,(unsigned long)min,(unsigned long)second];
        }
        return timeStr;
    }
    
    // do something when the The countdown ends
    - (void)countDownFinished
    {
        
    }
    
    
    

    注意:倒计时开始会有一秒的刷新空档期,可以铺上倒计时数据防止倒计时UI一片白.(如果有刷新,刷新的时候要更新数据源 self.dataArray)。
    我用的tableview,所以就在cell上铺。

    NSInteger backTime = [self.dataArray[indexPath.row] integerValue];
        NSString *backStr  = [self lessSecondToDay:backTime];
        cell.countDownLabel.text = backStr;
    

    最后附上方案二的github链接 倒计时Demo

    ps:如果有好的思路欢迎拍砖交流哈。

    相关文章

      网友评论

      • 奔跑的_猿:但是这样后台生成的秒数不会因为网络延迟而导致,客户端时间和后台偏差?
      • 羊肉泡馍啊:我用这个试了下
        - (void)dealloc{
        NSLog(@"%@ dealloc",NSStringFromClass([self class]));
        }你的控制器没有释放,你有考虑过NSTimer释放的问题吗
        夜的v:@秋天的菠菜_9cb1 我当时做的时候是常驻界面,就没做销毁。需要销毁的话就失效置空就好了
      • 404d1c5af490:兄弟,app进入后台怎么处理
        夜的v:@Pythonppp 恩。确实有不妥的地方,我看也有人是自己算的。。我做的简单就直接刷新了接口。。
        404d1c5af490:@夜的v 你的意思是重新访问接口拿当前时间吗..那样并不合适吧...
        夜的v:可以考虑下从后台进入app时重新开启倒计时
      • 男神nick:兄弟,你的在tableview中时间定时器不会销毁吗 cell不是进入重用池了吗
        夜的v:@男神nick 你可以先试一下 :smile:
        男神nick:@夜的v 好吧 ,这样子呀。
        夜的v:@男神nick 定时器不在cell上的,定时器的作用是到特定时间了去刷新cell上控件的显示数据。
      • listen_to:兄弟,有精确到毫秒的吗?第二种方法精确到毫秒该怎么实现?
        夜的v: @listen_to 同理按需要减少的毫秒数开始倒计时,每次减少对应的毫秒数,计算方法也需修改下。你可以先试试,不过精度太高估计会太耗性能。

      本文标题:iOS商城类商品抢购倒计时那点事

      本文链接:https://www.haomeiwen.com/subject/tmgedttx.html