如果處理服務器與客戶端時間不一致的問題

  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 <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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • 概述 在多數移動應用中任何時候都只能有一個應用程序處于活躍狀態,如果其他應用此刻發生了一些用戶感興趣的那么通過通知...
    莫離_焱閱讀 6,560評論 1 8
  • 每個月都會重新組建一個新的團隊,對于每隊隊員的挑選,店長都是經過深思熟慮的,或許每個隊都會有沉默寡言的,會有活潑...
    濰坊泰華DDM店劉云閱讀 224評論 2 0
  • 其實是有難受很久了的。關于了很多東西 寫日記就不用在乎那么多,格式啊,用詞啊,畫面聯想啊,云云 神煩。 經常是拔劍...
    Asirnmo閱讀 175評論 0 2
  • 陽光明媚,卻沒有暖意,院內高高的白楊樹上稀疏的葉子在風中瑟瑟地顫抖,偶爾有幾片葉蕭索地落下,不知是因風殷情的狂邀還...
    三公子唐閱讀 637評論 0 3