- 前一段時間做了一個倒計時的功能,要求每個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