Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/121.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UIApplicationExitOnSuspend用于挂起而不是后台_Ios_Swift - Fatal编程技术网

Ios UIApplicationExitOnSuspend用于挂起而不是后台

Ios UIApplicationExitOnSuspend用于挂起而不是后台,ios,swift,Ios,Swift,我有一个应用程序,由于它播放音乐,所以在后台往往保持清醒;但是,在极少数情况下,如果由于连接问题,音乐在两首歌曲之间停止的时间超过预期(可能相对较短),或者用户将音乐静音,则应用程序将暂停。我知道uiapplicationexitonsupend,但与对它的描述不同,它实际上是在进入后台时存在的。我做了大量的研究,我知道没有进入暂停状态的系统通知 在离开挂起状态时,是否仍然可以确定应用程序已挂起?或者,是否有任何方法可以执行类似于uiapplicationexitonsupend的操作,除非应用

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


在离开挂起状态时,是否仍然可以确定应用程序已挂起?或者,是否有任何方法可以执行类似于
uiapplicationexitonsupend
的操作,除非应用程序实际上被挂起,而不仅仅是在它进入后台时?

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


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

我创建了一个小类来标识应用程序何时进入挂起状态:

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

您似乎已经想到了一些可能不可能的事情,因为没有委托方法通知您从后台到挂起的状态转换。文件明确表示,你应该“做好被停职的准备”。我不想把重点放在这一点上,而是想办法防止由于连接问题或延迟而离开后台状态,并相应地调整问题。:)如果下载任务不够快,试着调整一下,让这里的人知道你在做什么,以及它是如何停止的(导致操作系统认为你已经完成并暂停了)。谢谢你的建议,我最后制作了一个小类,它会以一定的间隔递增。每当应用程序从后台返回时,它都会检查时间与实际时间的距离,这似乎很好地确定了应用程序是否已暂停。