- 前一段时间做了一个倒计时的功能,要求每个tableViewcell里面都嵌入倒计时的功能。我也封装了一个工具类,详细请看这里
- 但是倒计时如果不是用服务器的现在时间进行剩余时间计算的话,就可能出现bug
(比如一个商品,倒计时1小时停售,服务器已经过了这停售时间,从而停售了,但是客户端的时间比服务器时间向后调了1小时,那么客户端就会以为还没有停售)
- 这就要求要用客户端的时间求出服务器的时间
1、大体思路
其实很简单就说一下大体的思路,在附一个小的工具类,很简单。。。
- 封装一个类,在请求到后台的时间戳后,把本地时间与后台时间戳进行对比,记录时间差,最后每次时间计算的时候,都可以用本地时间求出服务器的时间。
- 关键是什么时候请求服务器时间。
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 <Foundation/Foundation.h>
@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