【问题标题】:Internal clock in iPhone background modeiPhone后台模式下的内部时钟
【发布时间】:2012-03-22 19:36:45
【问题描述】:

在我的应用程序中,我想在后台模式下运行一个内部时钟 [而应用程序不在前台运行时]。

整个功能是这样的:

目标是让服务器时间在应用程序中使用,因为使用设备时间有时可能会导致问题。问题可能出现在有人更改了用户的 iPhone 时间等情况下。所以我遵循以下方法。

-在我的应用程序后台运行一个内部时钟,即使应用程序没有运行。 - 每 15 分钟与服务器通信以获取实时时间并运行计时器。 - 如果中间网络断开,定时器将继续并占用定时器时间。

我的申请在很大程度上取决于这个时间因素,因为这是一个订票系统。请帮助我实现这个,或者请确认这是否可能?

我正在开发一个涉及票务预订系统的 iPhone 应用程序。我将我的应用程序注册为基于位置的应用程序,因为它出于某种目的使用在后台获取的用户位置。

我的问题是我需要在后台模式下在我的应用程序中运行一个内部时钟。我需要在核心位置委托方法中编写内部时钟的代码,以便内部时钟也将与位置 bsed 服务一起运行。我的应用程序会被拒绝吗?这样做有什么不对吗?

我需要在我的应用程序中使用正确的时间,以便我运行这个内部时钟。我可以使用 NSDate,但这会返回设备时间。任何人都可以更改设备时间。所以一旦有人更改,错误的时间会影响应用程序的流畅运行。请一些机构建议在不运行内部时钟的情况下获得正确的时间?

【问题讨论】:

标签: iphone ios xcode


【解决方案1】:

更新:很抱歉,我的原始答案不正确。当设备进入睡眠状态时(可能在锁定后的某个时间发生)内部 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,计算与您最初记录的差异,并显示正确的日期。

这仅在设备未关闭时才有效,在这种情况下,应用重新连接到服务器以获得正确的日期是有意义的。

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

【讨论】:

  • 这里唯一的问题是用户关闭设备时。有什么方法可以知道用户是否关闭并打开了他的设备?
【解决方案2】:

apple 支持后台模式的小任务,仅工作大约 10 秒。

所以您可以在应用程序处于活动状态时做一件事,然后获取时间表单服务器并据此更新您的本地时间。

【讨论】:

  • 是的,我考虑过...但是我们也必须考虑离线情况。如果没有网络连接,我们无法获取服务器时间。我们需要正确的时间,因为图像票证随着时间而变化。任何人都请提出一个适用于离线模式的解决方案......
  • 使用 NSDate 并将该时间转换为服务器时区。这会给你完美的时间。
  • @priyanka....如果用户更改了他的设备时间,这如何提供正确的时间?如果我只依赖设备时间,用户可以通过更改设备时间轻松破解我的应用程序...我正在寻求解决方案?
【解决方案3】:

我认为您只能检测到 iOs 设备的日期已更改(使用 NSSystemClockDidChangeNotification)。 我猜你会使用这个通知并从你的服务器强制重新加载你的应用程序的真实日期(使用 WebService)。

编辑:您可以在 NSProcessInfo 中使用 systemUptime:

 NSLog(@"ProcessInfo System uptime: %f",[NSProcessInfo processInfo].systemUptime);

但如果设备重新启动它不会解决您的问题。

【讨论】:

  • 我正在为一家旅行社开发这个。所以我必须考虑在预订旅程时间后没有网络连接的最坏情况。所以你的最后一句话是不可能的。谢谢你的建议NSSystemClockDidChangeNotification。变化的时间会不会体现在这上面?我需要在应用程序处于前台模式时调用此方法吗?或者这也可以在 bg 模式下工作?方法 applicationSignificantTimeChange: 怎么样,这有助于了解时间是否手动更改?
  • 通知 UIApplicationSignificantTimeChangeNotification 并不意味着设备的首选项窗格中的时钟已更改,这意味着时间发生了重大变化(例如日期已更改,...) .
  • 好的...所以它不会识别手动进行的小时间更改...请解释一下 NSProcessInfo?
【解决方案4】:

我认为有两种方法可以解决您的问题。

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

  2. 当应用程序启动或进入前台时,根据 NTP 服务器验证系统时间是否合理准确。如果系统时间超出您的容忍水平,那么在他们解决之前不要让他们继续运行应用程序。如果系统时间正常,则开始监控以确保他们在运行应用程序时不会更改系统时间(NSSystemClockDidChangeNotification)。如果他们通过了初始检查,但时钟向前移动,您可以抓住它并禁用应用程序,直到他们将其改回准确为止。

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

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

【讨论】:

    【解决方案5】:
    1. 时区设置不应像 UTC 那样影响时间
    2. 您的应用程序无法在后台运行。滥用位置要求将导致您的应用被 Apple 拒绝

    所以我的建议:用推送通知做逻辑服务器端

    【讨论】:

      猜你喜欢
      • 2016-03-14
      • 1970-01-01
      • 2015-12-13
      • 2011-06-11
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-20
      相关资源
      最近更新 更多