取消后台预定事件

Cancel scheduled event for background

所以我有这个功能,应该每 15 分钟上传一些录音数据到后端。即使用户将应用程序置于后台,这也应该发生。因此 Timer.schedule 不起作用。因此我发现我需要把它放在如下所示的 dispatchQueue 代码中:

    while Date(timeIntervalSinceNow: 86400).compare(Date(timeIntervalSinceNow: incrementer)) == .orderedDescending {
            incrementer += 900
            DispatchQueue.main.asyncAfter(deadline: .now() + incrementer, execute: {
                    DispatchQueue.main.async {
                        self.viewModel.upload(data: self.audioRecorder.url, filePath: self.audioRecorder.url)
                        self.audioRecorder.stop()
                        self.fileIncrementer += 1
                        self.startRecording()
                    }
            })
    }

当我通过按下停止按钮并显示下一个提前取消任务时,这怎么会导致问题viewController这个调度队列只是继续处理。

能做的就是扔进去:

    if var topController = UIApplication.shared.keyWindowInConnectedScenes?.rootViewController {
                        while let presentedViewController = topController.presentedViewController {
                            topController = presentedViewController
                        }
                        if (topController as? UINavigationController) != self.navigationController {
                            print("cought")
                            return
                        }
    }

如果我在另一个 VC 中,它会停止它,但如果我随后进入一个新会话,我将有双重事件。那么我该如何以一种好的方式做到这一点呢?

... when ... pressing stop button ... this is dispatchQueue just keep processing

是的,这正是您不应该使用这种多重 asyncAfter 模式的原因。 (另外,您最终可能会 运行 陷入计时器合并问题。)Timer 是正确的方法。

So i have this function that should upload some data of a recording every 15 minutes to backend. This should happen even if the user put the app in background.

这就是问题所在。 TimerasyncAfter都不能解决这个问题。

我推断你已经得出结论,你可以用 asyncAfter 完成这个,但你不能。也许您在 运行ning 应用附加到调试器时正在测试此过程,这人为地将应用 运行ning 保留在后台。但是在没有连接到调试器的设备上尝试它,你会发现当用户离开应用程序时,应用程序不会继续 运行。这种 asyncAfter 技术不会达到您想要的效果。

这里的例外情况是,如果您的应用程序请求了其中一项后台功能(例如 VOIP、音乐、导航等)。但如果该应用程序的目标是 App Store,Apple 会非常努力地拒绝那些出于未经批准的目的而请求后台服务的应用程序。这种持续不断的后台操作会在数小时内耗尽电池电量,因此 Apple 正在照顾其用户群的最大利益。

所以,归根结底,如果您的应用程序具有后台执行功能,Timer 是执行此周期性进程的方法。如果应用程序没有后台执行功能,Timer 和任何 GCD 调用都无法完成这项工作。