我試圖設計一個實時事件發生的系統,並且我想將它們同步到一個時鐘。 [NSDate date]
通常會正常,但用戶可以更改並欺騙系統。我需要的只是一個時鐘,我可以從相對時間(例如一個64位計數器) - 我不需要絕對時間(或一天的時間等)。在iOS中是否有可供用戶更改的時鐘
有沒有我可以使用的API?
編輯:我還想補充一點,這個時鐘需要在應用程序的會話上持久化。
我試圖設計一個實時事件發生的系統,並且我想將它們同步到一個時鐘。 [NSDate date]
通常會正常,但用戶可以更改並欺騙系統。我需要的只是一個時鐘,我可以從相對時間(例如一個64位計數器) - 我不需要絕對時間(或一天的時間等)。在iOS中是否有可供用戶更改的時鐘
有沒有我可以使用的API?
編輯:我還想補充一點,這個時鐘需要在應用程序的會話上持久化。
如果您只需要一個時鐘來測量單調增加的事件,則可以獲得當前系統的正常運行時間ala clock_gettime(CLOCK_MONOTONIC)
。如果重新啓動設備存在問題,請保存上次使用的值,並在下次啓動時使用上次保存的值作爲偏移量。這裏的問題可能是,如果他們真的關閉了設備,它不會計算那個時間。但是如果你擔心用戶加速時間,他們不能這麼做,只能放慢速度。
是否有'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)。我嘗試過包含/導入'
@EdMarty有沒有辦法找出設備是否重新啓動? – 2014-05-22 15:39:16
如果沒有跟蹤使用外部資源的時間(甚至是中間人,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
我能想到的唯一想法是使用NTP服務器獲取時鐘,但這需要網絡連接。
是的,我希望避免這種情況。 – Cthutu 2012-07-10 12:55:21
而且一個用戶確定足以僞造時鐘以欺騙也可能僞造您的NTP服務器。 – JeremyP 2012-07-10 14:17:50
當然,他們可以,但這是在複雜的用戶控制面板中的日期/時間設置的複雜性的重大飛躍。我有一些朋友,他們並不是技術嫺熟的人,他們已經發現他們可以通過這種方式欺騙遊戲(或者他們可能會在網上閱讀有關內容,無論如何),但這很容易做到。這些同樣的人不知道哪些NTP很少有欺騙服務器的動機或能力,即使對於經驗豐富的黑客來說很容易。 – Suboptimus 2013-05-01 19:21:32
我知道,沒有其他方法可以獲得正確的時間。我會用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
我認爲mach_absolute_time()
可能是你想要的。這裏有相當多的信息:http://developer.apple.com/library/mac/#qa/qa1398/_index.html
它基本上是自設備啓動以來的滴答數的計數器。這將在重新啓動時重置,但除此之外它是一個單調遞增的計數器。
如果自上次(設備重新啓動後)計數器已減少,您可以保留計數器的最後一個值並對其進行處理。在這種情況下,您可以將最後一個已知值添加到當前值以獲得已過去時間的下限,所有您將丟失的是最後一個會話和設備關閉之間的時間,您可以將時間儘管重啓和下一個會話。
他需要一個跨會話持久性的時鐘,所以這不會有幫助。 – Almo 2012-07-10 13:06:12
mach_absolute_time()僅在重啓設備時重置。 – hypercrypt 2012-07-10 13:08:41
如果您想象用戶重置iPhone,玩遊戲並在5分鐘後關閉遊戲,然後再重置iPhone並在5分鐘後玩遊戲的場景,計數器可能沒有減少。但它似乎是最可靠的方法 - 我只會失去時間,但不會加速。 – Cthutu 2012-07-10 14:15:01
iPhone上單調遞增最好的數字是mach_absolute_time()
,它是自上次重新啓動以來的CPU滴答數量。如果您因爲任何原因在幾秒鐘內想要它,最容易被CACurrentMediaTime()
獲取。
使用它創建一個「永遠增量」非常簡單。在第一次啓動時,將當前值存儲在任何你喜歡的地方。退出時,並定期保存該值的偏移量。重新啓動時,檢查當前值;如果它小於以前的基準值,請更換基準值(重新啓動)。
所有這些當然都可以通過刪除應用程序來清除,除非您在服務器上存儲了某些內容。
請注意,這不能用作強有力的安全措施。無法阻止授權用戶僞造請求。因此,根據「欺騙系統」的含義,這可能不是一個可解決的問題。你所能做的最好的事情是不斷努力尋找黑客並與他們打交道。
只是要注意,檢查值是否較少並不表示肯定有重啓或不重啓。用戶可能已經重新啓動,然後等待超過最後記錄的時間。 – Gukki5 2017-07-31 21:59:56
我在我們的應用程序使用此
+ (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;
}
經驗法則是:「如果它是在用戶的設備上,他能惹它。」這可能不是100%真實的,但它非常接近。 – Almo 2012-07-10 12:57:23
但是,必須有一個低級的持久時鐘(即使通過公共API無法訪問)。如果不是,設備如何知道打開時間?如果你可以使用它,你至少可以在兩次會話之間獲得相對的秒數。 – 2012-07-10 12:59:23
該設備可能會在上次關機和啓動之間經過一段時間,但一旦啓動,它就可能與之混淆,並且在您的應用程序啓動時,所有投注都將關閉。 – Almo 2012-07-10 13:07:02