如果处理服务器与客户端时间不一致的问题

  1. 前一段时间做了一个倒计时的功能,要求每个tableViewcell里面都嵌入倒计时的功能。我也封装了一个工具类,详细请看这里
  1. 但是倒计时如果不是用服务器的现在时间进行剩余时间计算的话,就可能出现bug(比如一个商品,倒计时1小时停售,服务器已经过了这停售时间,从而停售了,但是客户端的时间比服务器时间向后调了1小时,那么客户端就会以为还没有停售)
  2. 这就要求要用客户端的时间求出服务器的时间

1、大体思路

其实很简单就说一下大体的思路,在附一个小的工具类,很简单。。。

  1. 封装一个类,在请求到后台的时间戳后,把本地时间与后台时间戳进行对比,记录时间差,最后每次时间计算的时候,都可以用本地时间求出服务器的时间。
  2. 关键是什么时候请求服务器时间。
    1.我们先分析一下,首先,这种时间差,越早知道越好,所以,在app启动的时候就要请求服务器时间,并计算差值。
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
    app刚刚启动的时候创建并给出serverTime,内部计算了服务器时间

2.假设,用户很调皮,在app运行后,就退出去,对手机的时间设置成一个随意时间。那再进来,再用以前储存的时间差计算服务器时间,岂不是炸了。
所以在app进入后台、应用程序编程不激活状态、从后台进入到前台等都要调用一下,一下代码满足了这些时机的需求

-(void)applicationWillResignActive:(UIApplication *)application {}
    应用程序变成不激活状态,双击home建,应用程序不在相应用户点击的时候
-(void)applicationDidEnterBackground:(UIApplication *)application{}
    应用程序进入到后台的时候调用,双击home建不会调用
-(void)applicationWillEnterForeground:(UIApplication *)application{}
    应用程序从后台进入到前台以后调用这个方法, 应用启动不会调用
-(void)applicationDidBecomeActive:(UIApplication *)application{}
    应用程序变为激活状态的时候会调用这个方法,(用户可以进行用户交互的时候调用)
-(void)applicationWillTerminate:(UIApplication *)application{}
    系统将要推出(终止)的时候调用

2. 代码剪辑
.h

#import 
@interface PYServerAndClientTime : NSObject
///单利
+ (instancetype) sharedServerAndClientTime;
///内部创建了sharedServerAndClientTime对象
+ (instancetype) serVerAndClientTimeWithServerTime: (NSString *)serverTime;
///服务器的时间戳
@property (nonatomic,copy) NSString *serverTime;
///计算后的服务器时间
@property (nonatomic,strong,readonly) NSDate *serverAndClientDate;
///计算后服务器时间的timeInterval
@property (nonatomic,assign,readonly) NSNumber *serverAndClientTimeInterval;
///服务器与客户端时间的时间差
@property (nonatomic,assign,readonly) NSNumber *timeDifference;
@end

.m

@implementation PYServerAndClientTime
+ (instancetype) sharedServerAndClientTime {
    static dispatch_once_t onceToken;
    static PYServerAndClientTime *_instance;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc]init];
    });
    return _instance;
}


+(instancetype) serVerAndClientTimeWithServerTime: (NSString *)serverTime {
    PYServerAndClientTime *serverAndClientTime = [PYServerAndClientTime sharedServerAndClientTime];
    serverAndClientTime.serverTime = serverTime;
    return serverAndClientTime;
}
//MARK: setter
-(void)setServerTime:(NSString *)serverTime {
    _serverTime = serverTime;
   double serverTimeDouble = serverTime.longLongValue;
    //计算当前的时间秒数
    NSTimeInterval currentDateInterval = [[[NSDate alloc]init] timeIntervalSince1970];
    //计算时差
     NSNumber *timeDifferenceTemp = @(serverTimeDouble - currentDateInterval);
    [self setValue:timeDifferenceTemp forKey:@"timeDifference"];
}
//MARK: getter
-(NSDate *)serverAndClientDate {
    return [NSDate dateWithTimeIntervalSinceNow:self.timeDifference.doubleValue];;
}
-(NSNumber *)serverAndClientTimeInterval {
    return @([self.serverAndClientDate timeIntervalSince1970]);
}
@end

appDelegate

#import "AppDelegate.h"
#import "PYServerAndClientTime.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
//根据服务器时间计算与本地时间的时间差
-(void)serverAndClientTime {
    /**......
     服务器请求数据
     .......
     */
    NSString *serverTime;//服务器求情下来之后的服务器时间戳
    PYServerAndClientTime *serverAndClientTime = [PYServerAndClientTime sharedServerAndClientTime];
    serverAndClientTime.serverTime = serverTime;
}
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //app刚刚启动的时候创建并给出serverTime,内部计算了服务器时间
    [self serverAndClientTime];
    return YES;
}
-(void)applicationWillResignActive:(UIApplication *)application {
    // 应用程序变成不激活状态,双击home建,应用程序不在相应用户点击的时候
    [self serverAndClientTime];
}
-(void)applicationDidEnterBackground:(UIApplication *)application {
    //应用程序进入到后台的时候调用,双击home建不会调用
  [self serverAndClientTime];
}

-(void)applicationWillEnterForeground:(UIApplication *)application {
    //应用程序从后台进入到前台以后调用这个方法, 应用启动不会调用
  [self serverAndClientTime];
}
-(void)applicationDidBecomeActive:(UIApplication *)application {
    //应用程序变为激活状态的时候会调用这个方法,(用户可以进行用户交互的时候调用)
   [self serverAndClientTime];
}
-(void)applicationWillTerminate:(UIApplication *)application {
   //系统将要推出(终止)的时候调用
}
@end

你可能感兴趣的:(如果处理服务器与客户端时间不一致的问题)