iOS關(guān)于時(shí)間的處理(二)—— 客戶端和服務(wù)器的時(shí)間同步問題解決

版本記錄

版本號 時(shí)間
V1.0 2017.08.30

前言

很多時(shí)候我們是需要服務(wù)器和客戶端時(shí)間的同步的,比如說活動(dòng)的倒計(jì)時(shí)碴犬,搶購等。而且做好時(shí)間同步還有一個(gè)優(yōu)勢就是防止客戶端用戶本地時(shí)間有誤差導(dǎo)致問題。感興趣的可以看上面幾篇停做。
1. iOS關(guān)于時(shí)間的處理(一)—— 有關(guān)時(shí)間的基本知識

功能要求

要做到客戶端和服務(wù)器端時(shí)間同步。


功能實(shí)現(xiàn)

1. 問題分析

我們可以按照下面的思路進(jìn)行

  • 獲取服務(wù)器某一時(shí)刻 A 的時(shí)間大莫;
  • 記錄獲取到時(shí)刻 A 時(shí)的本地時(shí)間 B蛉腌;
  • 需要用到時(shí)間時(shí),獲取當(dāng)前本地時(shí)間 C,當(dāng) C - B 作為時(shí)間間隔 D烙丛,則 A + D 則是當(dāng)前服務(wù)器的時(shí)間舅巷。

這里要準(zhǔn)確做到客戶端時(shí)間和服務(wù)器時(shí)間一致,很關(guān)鍵的問題就是B和C不能受系統(tǒng)時(shí)間的影響河咽。要解決這個(gè)問題钠右,要依靠iOS的兩個(gè)接口。

  • 獲取設(shè)備當(dāng)前時(shí)間 Now库北,該值受系統(tǒng)時(shí)間影響爬舰,用戶如果修改時(shí)間,值也會隨著變化寒瓦。
  • 獲取設(shè)備上次重啟的時(shí)間 BootTime情屹,該值受系統(tǒng)時(shí)間影響,用戶如果修改時(shí)間杂腰,值也會隨著變化垃你。

由上面 iOS 提供的兩個(gè)接口,我們可以獲取本地時(shí)間 B喂很、C:設(shè)備自上次重啟后運(yùn)行的時(shí)間(BootTime - Now)惜颇,該值與系統(tǒng)時(shí)間無關(guān)。利用時(shí)間差這一概念就很好的解決了時(shí)間受系統(tǒng)影響的這個(gè)問題了少辣。

2. 代碼實(shí)現(xiàn)

  • 獲取當(dāng)前 Unix Time
static func now() -> Int {
        var now =  timeval()
        var tz = timezone()
        gettimeofday(&now, &tz)
        return now.tv_sec
 }
  • 獲取設(shè)備上次重啟的 Unix Time
func boottime() -> Int {

        var mid = [CTL_KERN, KERN_BOOTTIME]
        var boottime = timeval()
        var size = MemoryLayout.size(ofValue: boottime)

        if sysctl(&mid, 2, &boottime, &size, nil, 0) != -1 {
            return boottime.tv_sec
        }
        return 0
 }
  • 進(jìn)行時(shí)間校準(zhǔn)
// 接口獲取服務(wù)器時(shí)間處理
let serverTime = xxx                        // 獲取到的服務(wù)器時(shí)間
let runTime0 = now() - boottime()            // 當(dāng)前設(shè)備運(yùn)行時(shí)間

// 需要用到時(shí)間時(shí)
let runTime1 = now() - boottime()            // 當(dāng)前時(shí)刻設(shè)備運(yùn)行時(shí)間
let currentTime = serverTime + runTime1     // 當(dāng)前服務(wù)器時(shí)間

題外話

關(guān)于時(shí)間的使用凌摄,還有另外一個(gè)用途就是時(shí)間的測量,在做方法執(zhí)行時(shí)間的benchmark的時(shí)候漓帅,我們獲取時(shí)間的方法要滿足兩個(gè)要求锨亏,一是精讀要高,而是API本身幾乎不耗CPU時(shí)間忙干。一般認(rèn)為UI線程只要阻塞16.7ms就會出現(xiàn)掉幀現(xiàn)象器予,第一篇中提到的幾種時(shí)間的方法,其中NSDate調(diào)用返回的精讀是0.000004 S捐迫,也就是4微秒乾翔,CACurrentMediaTime()返回的精讀也在微秒級別,精讀上都符合要求施戴。

下面看一下別人提供的示例代碼

int testCount = 10000;
double avgCost = 0;
for (int i = 0; i < testCount; i ++) {
    NSDate* begin = [NSDate date];
    NSLog(@"a meaningless log");
    avgCost += -[begin timeIntervalSinceNow];
}
NSLog(@"benchmark with NSDate: %f", avgCost/testCount);

avgCost = 0;
for (int i = 0; i < testCount; i ++) {
    double startTime = CACurrentMediaTime();
    NSLog(@"a meaningless log");
    double endTime = CACurrentMediaTime();
    avgCost += (endTime - startTime);
}
NSLog(@"benchmark with CACurrentMediaTime: %f", avgCost/testCount);

下面看輸出結(jié)果

benchmark with NSDate: 0.000046
benchmark with CACurrentMediaTime: 0.000037

可以看出CACurrentMediaTimeNSDate代碼本身的損耗差異在幾微秒反浓,而我們做UI性能優(yōu)化的維度在毫秒級別,幾個(gè)微秒的差異完全不會影響我們最后的判斷結(jié)果赞哗。所以使用NSDate做benchmark完全是可行的勾习。

參考文章

1. iOS 客戶端與服務(wù)端做時(shí)間同步
2. iOS關(guān)于時(shí)間的處理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市懈玻,隨后出現(xiàn)的幾起案子巧婶,更是在濱河造成了極大的恐慌乾颁,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艺栈,死亡現(xiàn)場離奇詭異英岭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)湿右,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門诅妹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人毅人,你說我怎么就攤上這事吭狡。” “怎么了丈莺?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵划煮,是天一觀的道長。 經(jīng)常有香客問我缔俄,道長弛秋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任俐载,我火速辦了婚禮蟹略,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遏佣。我一直安慰自己挖炬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布状婶。 她就那樣靜靜地躺著意敛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪太抓。 梳的紋絲不亂的頭發(fā)上空闲,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天令杈,我揣著相機(jī)與錄音走敌,去河邊找鬼。 笑死逗噩,一個(gè)胖子當(dāng)著我的面吹牛掉丽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播异雁,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼捶障,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纲刀?” 一聲冷哼從身側(cè)響起项炼,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后锭部,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暂论,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年拌禾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了取胎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡湃窍,死狀恐怖闻蛀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情您市,我是刑警寧澤觉痛,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站墨坚,受9級特大地震影響秧饮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泽篮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一盗尸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帽撑,春花似錦泼各、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至及塘,卻和暖如春莽使,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背笙僚。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工芳肌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肋层。 一個(gè)月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓亿笤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親栋猖。 傳聞我的和親對象是個(gè)殘疾皇子净薛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自:iOS關(guān)于時(shí)間的處理 做App避免不了要和時(shí)間打交道,關(guān)于時(shí)間的處理蒲拉,里面有不少門道肃拜,遠(yuǎn)不是一行API調(diào)用痴腌,...
    咖啡綠茶1991閱讀 692評論 0 0
  • 做App避免不了要和時(shí)間打交道,關(guān)于時(shí)間的處理燃领,里面有不少門道衷掷,遠(yuǎn)不是一行API調(diào)用,獲取當(dāng)前系統(tǒng)時(shí)間這么簡單柿菩。我...
    MrPeak閱讀 4,635評論 0 42
  • 前言 在iOS開發(fā)過程中戚嗅,經(jīng)常會和時(shí)間打交道。例如用戶在一個(gè)頁面停留的時(shí)間枢舶、兩個(gè)方法哪個(gè)執(zhí)行更快等等懦胞。之前對于這部...
    WQ_UESTC閱讀 3,308評論 0 12
  • 場景一,時(shí)間測量 我們做性能優(yōu)化的時(shí)候凉泄,經(jīng)常需要對某個(gè)方法執(zhí)行的時(shí)間做記錄躏尉,就必然會用到上面提到的一些獲取時(shí)間的方...
    介和閱讀 1,047評論 0 0
  • 版本記錄 前言 做app一定會和時(shí)間打交道,關(guān)于時(shí)間的處理有很多值得我們研究和注意的地方后众,時(shí)間是線性的胀糜,地球上各個(gè)...
    刀客傳奇閱讀 1,516評論 0 1