【问题标题】:UIApplicationExitOnSuspend for Suspend not BackgroundUIApplicationExitOnSuspend 用于暂停而不是背景
【发布时间】:2017-06-07 23:20:26
【问题描述】:

我有一个应用程序,由于它在播放音乐,它往往会在后台保持清醒;但是,在极少数情况下,如果由于连接问题或用户将音乐静音,应用程序在歌曲之间停止的时间比预期的长(可能是相对较短的时间),应用程序将暂停。我知道UIApplicationExitOnSuspend 但与它的描述不同,这实际上在进入后台时退出。我做了相当多的研究,我知道没有进入挂起状态的系统通知。

离开 暂停状态时,是否可以确定应用程序已暂停?或者,除了应用程序实际被挂起而不仅仅是当它进入后台时,是否还有其他类似于UIApplicationExitOnSuspend 的操作?

【问题讨论】:

  • 您似乎已经想到了一些可能不可能的事情,因为没有委托方法通知您从后台到暂停的状态转换。文档明确表示您应该“准备被暂停”。而不是试图专注于此,我会寻找一种方法来防止由于连接问题或延迟而离开后台状态并相应地调整问题。 :) 如果下载任务不够快,请尝试对其进行调整,让这里的人知道您在做什么以及如何停止(导致操作系统认为您已完成并暂停您)。

标签: ios swift


【解决方案1】:

您可以尝试在 UIApplication 上使用backgroundtimeremaining 属性,在某个时间间隔使用计时器对其进行轮询,如果该值足够接近零 - 设置一个标志,甚至是 userDefaults 中的一个值,然后您可以检查回到前台后未设置?

The documentation reads:

此属性包含应用程序在被系统强行杀死之前必须在后台运行的时间量。当应用程序在前台运行时,此属性中的值保持适当大。如果应用使用 beginBackgroundTask(expirationHandler:) 方法启动一个或多个长时间运行的任务,然后转换到后台,则调整此属性的值以反映应用剩余的运行时间。

【讨论】:

  • 感谢您的建议,我最终制作了一个按间隔递增的小班。每当应用从后台返回时,它都会检查时间与实际时间的差距,这似乎可以很好地确定应用是否已暂停。
【解决方案2】:

我最终创建了一个小类来识别应用何时进入暂停状态:

class SuspendedMonitor {
  static let shared = SuspendedMonitor()

  var delegate: SuspendedMonitorDelegate?

  private let Interval = 10.0

  private let MaxDelta = 2.0

  private var _timestamp: Double

  private var _timer: Timer?

  private init() {
    _timestamp = timeInMs()
  }

  public func start() {
    _timestamp = timeInMs()

    NotificationCenter.default.addObserver(
      self,
      selector: #selector(enterForeground),
      name: NSNotification.Name.UIApplicationWillEnterForeground,
      object: nil
    )

    NotificationCenter.default.addObserver(
      self,
      selector: #selector(enterBackground),
      name: NSNotification.Name.UIApplicationDidEnterBackground,
      object: nil
    )
  }

  @objc func enterForeground() {
    checkSync()
    _timer?.invalidate()
  }

  @objc func enterBackground() {
    _timestamp = timeInMs()
    setupTimer()
  }

  @objc func incrementTime() {
    _timestamp = _timestamp + (Interval * 1000)
  }

  private func setupTimer() {
    _timer = Timer.scheduledTimer(
      timeInterval: Interval,
      target: self,
      selector: #selector(incrementTime),
      userInfo: nil,
      repeats: true
    )
  }

  private func checkSync() {
    if timeInMs() - _timestamp > ((Interval + MaxDelta) * 1000) { appSuspended() }
  }

  private func appSuspended() {
    delegate?.appDidSuspend(self)
  }

}

protocol SuspendedMonitorDelegate: class {
  func appDidSuspend(_ monitor: SuspendedMonitor)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    相关资源
    最近更新 更多