最近在做一个电商项目的时候遇到一个问题,就是在订单详情页显示“秒杀抢购倒计时”的时候,当APP退到后台运行一段时间后重新回到前台,倒计时显示的时间为APP退到后台那一瞬间的时间,而不是应当倒计时到的正确的时间,必须要重新进入页面刷新数据后才会显示正确的时间。原因很简单,因为iOS程序进入后台运行,程序很快就会被系统“杀死”,所以定时器会停止执行计时操作。
解决方法:监听APP进入后台、回到前台的通知,在进入后台的时候存一下时间戳,停掉定时器(系统会强制停止定时器),再在进入前台时计算时间差。若剩余的时间大于时间差,就减去时间差,否则赋值剩余时间为0。
具体核心代码如下所示:
@interface OrderDetailsHeaderView ()
@property (nonatomic,strong) NSTimer *timer;
@property (nonatomic,assign) NSInteger seconds;
@property (nonatomic,assign) NSTimeInterval timestamp;
@end
@implementation OrderDetailsHeaderView
/**
01 退款成功
02 退款中
03 已完成
04 已支付
05 已取消
06 待付款
*/
#pragma mark - setter
- (void)setTheOrderModel:(TheOrderModel *)theOrderModel
{
_theOrderModel = theOrderModel;
if ([theOrderModel.status isEqualToString:@"04"]) {
self.stateLbl.text = @"已付款";
self.invoiceBtn.hidden = NO;
self.repurchaseBtn.hidden = NO;
}else if ([theOrderModel.status isEqualToString:@"05"]) {
self.stateLbl.text = @"已取消";
self.repurchaseBtn.hidden = NO;
}else if ([theOrderModel.status isEqualToString:@"06"]) {
self.stateLbl.text = @"待付款";
//开始监听App进入前后台通知
[self observeApplicationActionNotification];
//秒杀倒计时按钮
self.payBtn.hidden = NO;
[self.payBtn seckillCountDown:theOrderModel.leftPayTime.intValue normalTitle:@"" countDownTitle:@"去支付" normalBGColor:COLOR(clearColor) countDownBGColor:COLOR(clearColor)];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(countBack) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
self.seconds = theOrderModel.leftPayTime.intValue;
self.cancelOrderBtn.hidden = NO;
}
}
#pragma mark - 监听App进入前后台通知
- (void)observeApplicationActionNotification
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)applicationDidEnterBackground
{
self.timestamp = [NSDate date].timeIntervalSince1970;
self.timer.fireDate = [NSDate distantFuture];
}
- (void)applicationDidBecomeActive
{
NSTimeInterval timeInterval = [NSDate date].timeIntervalSince1970 - self.timestamp;//计算时间差
self.timestamp = 0;
if (self.seconds - timeInterval > 0) {
self.seconds = self.seconds - timeInterval;
self.timer.fireDate = [NSDate date];
//重新显示商品秒杀倒计时
[self.payBtn removeFromSuperview];
self.payBtn = [HELPER buttonWithSuperView:self andNormalTitle:@"" andNormalTextColor:THEME_COLOR andTextFont:14 andNormalImage:nil andCornerRadius:15 backgroundColor:COLOR(whiteColor) addTarget:self action:@selector(toPayFor:) forControlEvents:UIControlEventTouchUpInside andMasonryBlock:^(MASConstraintMaker * _Nonnull make) {
make.centerY.equalTo(self);
make.width.equalTo(@100);
make.right.equalTo(self.cancelOrderBtn.mas_left).offset(-10);
make.height.equalTo(@30);
}];
self.payBtn.layer.borderColor = THEME_COLOR.CGColor;
self.payBtn.layer.borderWidth = 1;
[self.payBtn seckillCountDown:self.seconds normalTitle:@"" countDownTitle:@"去支付" normalBGColor:COLOR(clearColor) countDownBGColor:COLOR(clearColor)];
}else{
self.seconds = 0;
[self.timer invalidate];
self.timer = nil;
//取消订单
[self cancelOrder];
}
}
/**
timer倒计时
*/
- (void)countBack
{
self.seconds --;
if (self.seconds == 0) {
[self.timer invalidate];
self.timer = nil;
for (UIView *view in self.subviews) {
[view removeFromSuperview];
}
//取消订单
[self cancelOrder];
}
}
#pragma mark - 取消订单操作
- (void)cancelOrder
{
}
- (void)dealloc
{
[self.timer invalidate];
self.timer = nil;
}