iOS商城類商品搶購倒數計時那點事

weixin_34292287發表於2016-06-12

一.之前電商專案做過的倒數計時功能,筆記一下。
主要有兩種思路:①:根據當前系統時間和搶購結束時間計算差值,計算倒數計時。 ②:後臺返回當前時間距離搶購結束時間的總秒數。根據秒數本地倒數計時。(第二種方案更為準確,不受本地時間誤差的影響)

程式碼如下:

方案一:根據當前系統時間和搶購結束時間計算差值,計算倒數計時。在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://upload-images.jianshu.io/upload_images/1486049-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:如果有好的思路歡迎拍磚交流哈。

相關文章