iPhone 后台模式下的内部时钟

4
在我的应用程序中,我想在后台模式下运行一个内部时钟 [即使应用程序未在前台运行]。
整个功能如下:
目的是获取服务器时间以在应用程序中使用,因为使用设备时间有时可能会导致问题。问题可能出现在某人更改了用户的iPhone时间等情况下。所以我遵循以下方法。
-即使应用程序未运行,也要在应用程序后台运行内部时钟。 -每15分钟与服务器通信以获取实际时间并运行计时器。 -如果网络在中途断开,计时器将继续并采取计时器时间。
我的应用程序严重依赖于这个时间因素,因为这是一个售票系统。请帮助我实现这一点或确认是否可能?
我正在开发一个涉及售票系统的iPhone应用程序。我注册了我的应用程序作为基于位置的应用程序,因为它在后台使用用户的位置。
我的问题是,我需要在我的应用程序中以后台模式运行一个内部时钟。我需要在核心位置委托方法中编写内部时钟代码,以便内部时钟也可以与位置服务一起运行。我的应用程序会被拒绝吗?这样做有什么问题吗?
我需要获取正确的时间以在我的应用程序中使用,所以我正在运行此内部时钟。我可以

请访问以下链接以获取有关如何获取iOS系统运行时间的信息:https://dev59.com/0Wcs5IYBdhLWcg3w64Ca#12490414 - Russell Quinn
5个回答

14

更新:很抱歉,我的原始答案是不正确的。当设备进入睡眠状态(可能发生在锁定后的某个时候)时,内部CPU时钟停止计时,mach_absolute_time也不会更新。理论上,如果您在设备进入睡眠状态之前和之后立即调用它,它将返回完全相同的值。

我知道的检查日期更改的最佳方法是kern.boottime,它保存了启动时间,并且在系统时间更改时进行修改。除其他事项外,如果用户更改时间或操作系统根据来自基站的信息更改时间,kern.boottime也将得到更新。

因此,在您的情况下,您可以采用您计算出的原始时间,并根据kern.boottime中的修改进行修改。如果您看到kern.boottime发生了显着变化,则可能意味着设备已关闭,在这种情况下,您需要联系服务器询问飞行时间。

相关代码:

time_t getBootTimeSecs(void)
{
    struct timeval boottime;    
    size_t size = sizeof(boottime);
    int ret = sysctlbyname("kern.boottime", &boottime, &size, NULL, 0);
    assert(ret == 0);
    return boottime.tv_sec;
}

原文:你可以使用mach_absolute_time,它不会受到用户更改日期的影响。

当您订票时,从服务器获取正确的日期并记录mach_absolute_time。现在,您随时都可以调用mach_absolute_time,计算与初始记录的时间差,并显示正确的日期。

只要设备没有关闭,这将起作用,在这种情况下,应用程序重新连接服务器以获取正确的日期是有意义的。

您也可以使用本地或推送通知来提醒用户目标日期越来越近,即使应用程序没有运行。


这里唯一的问题是当用户关闭设备时。有没有办法知道用户是否关闭或打开了他的设备? - Praveen

2

苹果支持小任务在后台模式下工作,仅可工作约10秒钟。

因此,当应用程序处于活动状态时,您可以获取来自服务器的时间,并根据该时间更新本地时间。


是的,我考虑过这个问题...但我们还必须考虑离线情况。如果没有网络连接,我们无法获取服务器时间。我们需要正确的时间,因为车票上的图像会随着时间而变化。请有人提出一个适用于离线模式的解决方案... - Praveen
1
使用NSDate并将其转换为服务器时区。这将给您完美的时间。 - priyanka
https://dev59.com/NW025IYBdhLWcg3weF6S - priyanka
@priyanka....如果用户更改了设备时间,这个方法如何提供正确的时间?如果我仅依赖于设备时间,用户可以轻松通过更改设备时间来破解我的应用程序...我正在寻求解决方案。 - Praveen

2
我认为你只能检测到iOs设备的日期是否被更改(使用NSSystemClockDidChangeNotification)。我建议你使用此通知,并通过WebService从服务器强制重新加载应用程序的实际日期。
编辑:你可以使用NSProcessInfo中的systemUptime。
 NSLog(@"ProcessInfo System uptime: %f",[NSProcessInfo processInfo].systemUptime);

但是,如果设备重新启动,它将无法解决您的问题。


我正在为一家旅行社开发这个项目。因此,我必须考虑到在预订车票后到旅行时间没有网络连接的最坏情况。所以你的最后一句话是不可能的。感谢您对NSSystemClockDidChangeNotification的建议。更改时间是否会反映在其中?我需要在应用程序处于前台模式时调用此方法吗?还是这也适用于后台模式?关于applicationSignificantTimeChange:方法,它是否有助于了解时间是否手动更改? - Praveen
1
UIApplicationSignificantTimeChangeNotification通知并不意味着设备的偏好设置中更改了时间时钟,而是表示时间发生了重大变化(例如一天已经过去...)。 - Julien
好的...所以它无法识别手动进行的微小时间更改..请解释一下NSProcessInfo? - Praveen

1
  1. 时区设置不应影响UTC时间
  2. 您的应用程序不能在后台运行。滥用位置要求将导致您的应用被苹果拒绝

因此,我的建议是:使用推送通知在服务器端执行逻辑。


1

我认为解决你的问题有两种方法。

  1. 永远不要使用系统时间。换句话说,在代码中永远不要调用[NSDate date]。当你需要当前时间时,调用NTP服务器。这当然会导致应用程序延迟,但会保证准确性。

  2. 当应用程序启动或进入前台时,请验证系统时间是否相对准确(与NTP服务器)。如果系统时间偏差超过您的容忍水平,则不要让他们继续运行应用程序,直到他们解决为止。如果系统时间没问题,则开始监视以确保他们在运行应用程序时不更改系统时间(NSSystemClockDidChangeNotification)。如果他们通过了初始检查,但将时钟向前移动,您可以捕获并禁用该应用程序,直到他们将其改回准确。

这是一个iOS NTP实现,可能有助于实现上述任一解决方案。 http://code.google.com/p/ios-ntp/

编辑:Ticketmaster应用程序使用技术#2,因此这似乎是需要系统时间正确的售票应用程序的合理解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接