【问题标题】:Is there a clock in iOS that can be used that cannot be changed by the useriOS中是否有可以使用但用户无法更改的时钟
【发布时间】:2012-07-09 22:44:09
【问题描述】:

我正在尝试设计一个发生实时事件的系统,并且我想将它们与时钟同步。 [NSDate date] 通常可以,但用户可以更改它并欺骗系统。我所需要的只是一个可以从(例如 64 位计数器)获取相对时间的时钟 - 我不需要绝对时间(或一天中的时间等)。

有没有这样的 API 我可以使用?

编辑:我还想补充一点,这个时钟需要在应用程序的会话中保持不变。

【问题讨论】:

  • 经验法则是:“如果它在用户的设备上,他可以弄乱它。”这可能不是 100% 正确,但非常接近。
  • 然而,必须有一个低级的、持久的时钟(即使无法通过公共 API 访问)。如果不是,设备如何知道开机时间?如果你能利用它,你至少可以得到会话之间经过的相对秒数。
  • 设备可能会在上次关机和这次开机之间经过时间,但一旦开机,它可能会被弄乱,到你的应用启动时,所有的赌注都已经结束了。

标签: objective-c ios time


【解决方案1】:

iPhone 上最好的单调递增数字是mach_absolute_time(),这是自上次重启以来的 CPU 滴答计数。如果您出于任何原因想要在几秒钟内获得它,使用CACurrentMediaTime() 最容易获取它。

使用它来创建“始终递增”非常简单。首次启动时,将当前值存储在您喜欢的任何位置。当您退出时,并定期保存该值的偏移量。重启时,检查当前值;如果它小于您之前的基础值,请替换您的基础值(已重新启动)。

所有这些当然可以通过删除你的应用程序来清除,除非你在服务器上存储了一些东西。

请注意,这不能用作强大的安全措施。没有办法阻止授权用户伪造请求。因此,取决于您所说的“欺骗系统”,这可能不是一个可解决的问题。您能做的最好的事情就是不断努力寻找黑客并处理它们。

【讨论】:

  • 只是要注意,检查值是否更小并不能确定是否有重新启动。用户可能已经重新启动,然后等待的时间超过了最后记录的滴答声。
  • CACurrentMediaTime() 和 mach_absolute_time() 的难点在于它们在设备不活动时停止运行。当您锁定设备并将其放入口袋时,它们会继续运行几分钟,然后然后在设备进入待机模式时暂停。
【解决方案2】:

如果您只需要一个时钟来测量单调递增的事件,您只需获取当前系统正常运行时间 ala clock_gettime(CLOCK_MONOTONIC)。如果重启设备有问题,只需保存上次使用的值,并在下次启动时使用上次保存的值作为偏移量。这里的问题可能是,如果他们真的关闭了设备,它就不会计算那个时间。但是,如果您担心用户会加快时间,他们不能这样做,只能放慢速度。

【讨论】:

  • clock_gettime(CLOCK_MONOTONIC) 的文档吗?我找到了this。我尝试包含/导入<time.h>,但Xcode 仍然无法识别CLOCK_MONOTONIC,并指责我隐含了clock_gettime() 的定义。
  • @EdMarty 有没有办法查明设备是否重新启动?
  • 如果不使用外部资源跟踪时间,就无法绝对确定(即使这样,中间人,等等,等等,等等)。也就是说,您可以跟踪自设备启动以来设备运行了多长时间(使用深奥的 sysctl 调用)。如果它小于您确定自上次检查以来它已被重置的确定。注意:您不想使用 mach_absolute_time(),因为它实际上会在设备处于睡眠状态时暂停。获取启动时间:@​​987654322@
【解决方案3】:

我在我们的应用程序中使用它

+ (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;
}

【讨论】:

  • 感谢您的代码。如果我决定使用时间服务器,我会使用它。目前我正在尝试避免网络连接。
  • 奇怪的事情。我用这段代码在 iPad Air 上得到“(null)”。使用较旧的 iPad(第 3 代)和模拟器,它可以工作!两者都运行 iOS 8.0.2。有什么想法吗?
  • 本周 S3 宕机时如何应对?
【解决方案4】:

我认为mach_absolute_time() 可能是您想要的。这里有不少资料:http://developer.apple.com/library/mac/#qa/qa1398/_index.html

它基本上是自设备启动以来滴答数的计数器。这将在重新启动时重置,但除此之外它是一个单调递增的计数器。

如果计数器自上次(设备重新启动)以来减少,您可以保留计数器的最后一个值并处理它。在这种情况下,您可以将最后一个已知值添加到当前值以获得已过去时间的下限,您所失去的只是最后一次会话和设备关闭之间的时间,您将保持之间的时间重启和下一个会话。

【讨论】:

  • 他需要一个跨会话持续的时钟,所以这不会有帮助。
  • mach_absolute_time() 仅在设备重启时重置。
  • 如果您想象用户重置iphone,玩游戏并在5分钟后关闭它,然后再次重置iphone并在5分钟后玩游戏的场景,计数器可能没有减少。但这似乎是最可靠的方法 - 我只会浪费时间但不会加快速度。
【解决方案5】:

据我所知,没有其他方法可以获取正确的时间。我会使用 NTP。

网络时间协议 (NTP) 是一种网络协议,用于通过分组交换、可变延迟数据网络同步计算机系统的时钟。更多:http://en.wikipedia.org/wiki/Network_Time_Protocol

在一个项目中,我将使用 NTP(明天我的问题),但我已经做了一些研究:

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

【讨论】:

    【解决方案6】:

    我能想到的唯一想法是使用 NTP 服务器来获取时钟,但这需要网络连接。

    【讨论】:

    • 是的,我希望避免这种情况。
    • 如果用户决心伪造时钟以作弊,也可能伪造您的 NTP 服务器。
    • 当然可以,但与搞乱用户控制面板中的日期/时间设置相比,这在复杂性上是一个重大飞跃。我有一些技术含量不高的朋友​​,他们发现他们可以通过这种方式欺骗游戏(或者他们可能在网上阅读过,无论如何),但这真的很容易做到。这些人根本不知道 NTP 有什么动机或能力来欺骗服务器,即使对于经验丰富的黑客来说这很容易。
    • @Suboptimus,好点子。我仍然想知道当没有网络连接时应用程序会做什么。它应该停止工作,还是相信用户定义的时间?
    猜你喜欢
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    相关资源
    最近更新 更多