2012-07-10 40 views
24

我試圖設計一個實時事件發生的系統,並且我想將它們同步到一個時鐘。 [NSDate date]通常會正常,但用戶可以更改並欺騙系統。我需要的只是一個時鐘,我可以從相對時間(例如一個64位計數器) - 我不需要絕對時間(或一天的時間等)。在iOS中是否有可供用戶更改的時鐘

有沒有我可以使用的API?

編輯:我還想補充一點,這個時鐘需要在應用程序的會話上持久化。

+0

經驗法則是:「如果它是在用戶的設備上,他能惹它。」這可能不是100%真實的,但它非常接近。 – Almo 2012-07-10 12:57:23

+0

但是,必須有一個低級的持久時鐘(即使通過公共API無法訪問)。如果不是,設備如何知道打開時間?如果你可以使用它,你至少可以在兩次會話之間獲得相對的秒數。 – 2012-07-10 12:59:23

+0

該設備可能會在上次關機和啓動之間經過一段時間,但一旦啓動,它就可能與之混淆,並且在您的應用程序啓動時,所有投注都將關閉。 – Almo 2012-07-10 13:07:02

回答

6

如果您只需要一個時鐘來測量單調增加的事件,則可以獲得當前系統的正常運行時間ala clock_gettime(CLOCK_MONOTONIC)。如果重新啓動設備存在問題,請保存上次使用的值,並在下次啓動時使用上次保存的值作爲偏移量。這裏的問題可能是,如果他們真的關閉了設備,它不會計算那個時間。但是如果你擔心用戶加速時間,他們不能這麼做,只能放慢速度。

+1

是否有'clock_gettime(CLOCK_MONOTONIC)'的文檔?我發現[this](http://www.qnx.com/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fc%2Fclock_gettime.html)。我嘗試過包含/導入'',但Xcode仍然無法識別CLOCK_MONOTONIC,並且指責我隱式定義了'clock_gettime()'。 – JohnK 2013-07-27 18:44:45

+0

@EdMarty有沒有辦法找出設備是否重新啓動? – 2014-05-22 15:39:16

+0

如果沒有跟蹤使用外部資源的時間(甚至是中間人,blah,blah,blah),絕對沒有辦法。這就是說,你可以跟蹤自設備啓動以來設備運行了多長時間(使用深奧的sysctl調用)。如果它比較少,比你肯定知道自上次檢查以來它已被重置。 注意:您不想使用mach_absolute_time(),因爲在設備睡着時它實際上會暫停。 獲取啓動時間:http://stackoverflow.com/questions/10331020/get-the-boot-time-in-objective-c – 2014-05-22 20:49:07

1

我能想到的唯一想法是使用NTP服務器獲取時鐘,但這需要網絡連接。

+0

是的,我希望避免這種情況。 – Cthutu 2012-07-10 12:55:21

+0

而且一個用戶確定足以僞造時鐘以欺騙也可能僞造您的NTP服務器。 – JeremyP 2012-07-10 14:17:50

+3

當然,他們可以,但這是在複雜的用戶控制面板中的日期/時間設置的複雜性的重大飛躍。我有一些朋友,他們並不是技術嫺熟的人,他們已經發現他們可以通過這種方式欺騙遊戲(或者他們可能會在網上閱讀有關內容,無論如何),但這很容易做到。這些同樣的人不知道哪些NTP很少有欺騙服務器的動機或能力,即使對於經驗豐富的黑客來說很容易。 – Suboptimus 2013-05-01 19:21:32

3

我知道,沒有其他方法可以獲得正確的時間。我會用NTP。

網絡時間協議(NTP)是用於在分組交換,可變延遲數據網絡同步計算機系統的時鐘的網絡協議。更多:http://en.wikipedia.org/wiki/Network_Time_Protocol

在一個項目中,我將使用NTP(明天我quess),但我已經做了一些研究:

的iOS庫:https://github.com/jbenet/ios-ntp - 筆者注:執行並非如RFC中所描述的那樣嚴格,因爲其目標是在一秒鐘內提高時間精度,而不是幾分之一毫秒。

用於非商業項目的外觀上:www.packages.ubuntu.com/source/lucid/ntp

C庫: www.hillstone-software.com/hs_ntp_details.htm

文檔: www.nist.gov/pml/div688/grp40/its.cfm

5

我認爲mach_absolute_time()可能是你想要的。這裏有相當多的信息:http://developer.apple.com/library/mac/#qa/qa1398/_index.html

它基本上是自設備啓動以來的滴答數的計數器。這將在重新啓動時重置,但除此之外它是一個單調遞增的計數器。

如果自上次(設備重新啓動後)計數器已減少,您可以保留計數器的最後一個值並對其進行處理。在這種情況下,您可以將最後一個已知值添加到當前值以獲得已過去時間的下限,所有您將丟失的是最後一個會話和設備關閉之間的時間,您可以將時間儘管重啓和下一個會話。

+0

他需要一個跨會話持久性的時鐘,所以這不會有幫助。 – Almo 2012-07-10 13:06:12

+0

mach_absolute_time()僅在重啓設備時重置。 – hypercrypt 2012-07-10 13:08:41

+0

如果您想象用戶重置iPhone,玩遊戲並在5分鐘後關閉遊戲,然後再重置iPhone並在5分鐘後玩遊戲的場景,計數器可能沒有減少。但它似乎是最可靠的方法 - 我只會失去時間,但不會加速。 – Cthutu 2012-07-10 14:15:01

9

iPhone上單調遞增最好的數字是mach_absolute_time(),它是自上次重新啓動以來的CPU滴答數量。如果您因爲任何原因在幾秒鐘內想要它,最容易被CACurrentMediaTime()獲取。

使用它創建一個「永遠增量」非常簡單。在第一次啓動時,將當前值存儲在任何你喜歡的地方。退出時,並定期保存該值的偏移量。重新啓動時,檢查當前值;如果它小於以前的基準值,請更換基準值(重新啓動)。

所有這些當然都可以通過刪除應用程序來清除,除非您在服務器上存儲了某些內容。

請注意,這不能用作強有力的安全措施。無法阻止授權用戶僞造請求。因此,根據「欺騙系統」的含義,這可能不是一個可解決的問題。你所能做的最好的事情是不斷努力尋找黑客並與他們打交道。

+0

只是要注意,檢查值是否較少並不表示肯定有重啓或不重啓。用戶可能已經重新啓動,然後等待超過最後記錄的時間。 – Gukki5 2017-07-31 21:59:56

6

我在我們的應用程序使用此

+ (NSDate *) getAWSDate 
{ 
    NSDate *today = nil; 
    NSString *dateString = nil; 

    NSString *awsURL = @"http://s3.amazonaws.com"; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:awsURL]]; 
    [request setHTTPMethod:@"HEAD"]; 

    NSHTTPURLResponse *response; 
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error: NULL]; 

    if ([response respondsToSelector:@selector(allHeaderFields)]) { 
     dateString = [[response allHeaderFields] objectForKey:@"Date"]; 
     dateString = [dateString stringByReplacingOccurrencesOfString:@"GMT" withString:@"+0000"]; 
     NSDateFormatter *df = [[NSDateFormatter alloc] init]; 
    df.dateFormat = @"EEE, dd MMM yyyy HH:mm:ss z"; 
    df.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease]; 
    df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; 
    today = [df dateFromString:dateString]; 
    [df release];  
    }   
    return today; 
} 
+0

感謝您的代碼。如果我決定使用時間服務器,我會使用它。目前我正試圖避免網絡連接。 – Cthutu 2012-07-10 14:15:55

+0

奇怪的事情。使用此代碼在iPad Air上獲得「(null)」。隨着較舊的iPad(第三代)和模擬器,它的工作原理!都運行iOS 8.0.2。有任何想法嗎? – tomDev 2014-10-14 15:33:19

+0

本週S3下跌時,這是如何應對的? – 2017-03-05 20:33:28

相關問題