【问题标题】:DispatchQueue.global(qos: .default) continues when app is backgrounded or screen locked, how to suspend?DispatchQueue.global(qos: .default) 在应用程序后台或屏幕锁定时继续,如何暂停?
【发布时间】:2019-08-22 04:58:42
【问题描述】:

Swift 新手:将 Objective-C AppleHealth 集成代码移植到由 Flutter/Dart 调用的 Swift。当我背景或锁定旧版 Obj-C 应用程序时,它几乎会立即暂停所有执行。 但是,在我的 Swift 代码端口中没有发生相同的行为,我在 Swift 中使用与旧版 Obj-C 应用程序中相同的 DispatchQueue,

暂停很重要的原因是,一旦用户锁定 iPhone 屏幕,AppleHealth 会加密其所有数据,并且无法使用。 我的理解也是正确的,当您暂停 DispatchQueue 时,当前执行的块将完成,但后续块不会开始执行。 据我所知,Swift 代码移植模仿了 Obj-C 逻辑,任何关于它为何表现不同或我可能遗漏的任何提示都将不胜感激。

我正在使用

进行调度
DispatchQueue.global(qos: .default).async { 
/* code */ 
}

如果可以让新应用程序立即暂停我提交到 DispatchQueue 的所有执行代码,那么在后台或锁定屏幕时我会非常高兴。

【问题讨论】:

  • 您不能暂停DispatchQueue 任务。如果您需要更多控制权,您应该使用OperationQueue。这是两者之间的主要区别,如果在 DispatchQueue 块中写入了某些内容,则该任务将在某个时候执行。
  • @SharadChauhan - 在这方面,操作队列与自定义调度队列没有区别。如果您的应用程序仍在运行,挂起队列也不会挂起在 OperationQueue 上运行的操作。当你挂起一个操作队列时,它只会阻止新的操作开始。但正在进行的操作不会暂停。

标签: ios swift healthkit dispatch-queue


【解决方案1】:

当一个应用程序被挂起时,任何正在运行的东西,无论是在主队列还是后台global队列上,也会被挂起。

您是否在应用程序中执行任何操作以使其在后台运行?例如,如果您通过 Xcode 调试器运行应用程序(例如,您可以查看 print 语句或其他任何内容),它会更改应用程序生命周期并使其在后台运行。 (Xcode 的“观察者效应”?哈哈。)你是通过 Xcode 调试器运行它吗?

此外,如果您的应用启用了某些后台功能,这也可以使应用保持活动状态。

由于您无法通过 Xcode 调试器运行应用程序来查看应用程序生命周期,因此我将使用 Unified Logging 来演示该过程以监控我的应用程序的进度。使用统一日志记录,我可以从我的 macOS 控制台监控我的 iPhone 上的这些日志语句,甚至根本不需要运行 Xcode。

考虑类似:

import UIKit
import os.log

private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ViewController")

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        os_log("viewDidLoad", log: log, type: .debug)
        startTask()
    }

    func startTask() {
        DispatchQueue.global().async {
            var i = 0
            while true {
                let start = Date()
                while Date().timeIntervalSince(start) < 1 { }
                os_log("tick %d", log: log, type: .debug, i)
                i += 1
            }
        }
    }
}

(注意,通常你不应该这样旋转,但我这样做是为了有一个故意让 CPU 忙碌的进程。)

那么我:

  • 安装在我的设备上,
  • 退出 Xcode,
  • 启动了 macOS 控制台应用程序,
  • 在控制台应用程序中,我使用“操作”»“包含调试消息”启用了调试日志记录,
  • 过滤日志,所以我只能看到来自我的子系统的活动(我个人总是使用我的包标识符),并且
  • 直接在我的 iOS 设备上运行我的应用程序。

当我挂起应用程序时,我们可以清楚地看到应用程序停止(包括在后台队列上运行的此任务)。 (显然,除了上面的os_log 消息之外,我还在AppDelegate 中添加了类似的语句,这样我也可以在这里看到生命周期事件。)无论如何,这就是我的控制台显示的:

当“tick 5”出现时我离开了我的应用程序,在应用程序完全暂停之前需要几秒钟,但您可以看到应用程序在出现“tick 7”和“applicationDidEnterBackground”后停止运行。大约 10 秒后,我重新启动了应用程序,此时您会看到应用程序恢复生机并继续滴答作响,就在它停止的地方。

因此,如果您的应用程序仍在运行,则要么它已附加到 Xcode 调试器,要么您有一些东西使应用程序在后台运行。但一般来说,当您离开应用程序时,它会被暂停,您会看到我上面概述的行为。

顺便说一句,有关使用统一日志记录、配置设备等的更多信息,请参阅 WWDC 2016 视频Unified Logging and Activity Tracing

【讨论】:

  • 非常感谢 Rob,不知道统一日志,这正是我查看生命周期所需要的。
猜你喜欢
  • 1970-01-01
  • 2011-12-10
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多