UIApplicationExitOnSuspend for Suspend not Background

时间:2017-05-26 15:54:14

标签: ios swift

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

无论如何都要确定离开暂停状态该应用已暂停?或者,无论如何都要做类似于UIApplicationExitOnSuspend的事情,除非应用程序实际上被暂停,而不仅仅是当它进入后台时?

2 个答案:

答案 0 :(得分:1)

您可以尝试在UIApplication上使用backgroundtimeremaining属性,在某个时间间隔内使用计时器轮询它,并且该值应该足够接近零 - 设置一个标志,甚至是userDefaults中的值,您可以然后回到前台后检查并取消设置?

The documentation reads:

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

答案 1 :(得分:0)

我最终创建了一个小类,以确定应用程序何时进入暂停状态:

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)
}