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的所有执行代码,那么在后台或锁定屏幕时,我将非常高兴。
答案 0 :(得分:2)
应用程序暂停后,无论正在运行的主队列还是后台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繁忙。)
所以我然后:
当我挂起应用程序时,我们可以清楚地看到该应用程序停止运行(包括在后台队列中运行的此任务)。 (显然,除了上面的os_log
消息之外,我还在AppDelegate
中添加了类似的语句,以便在这里也可以看到生命周期事件。)无论如何,这就是控制台显示的内容:>
当“ tick 5”出现时我离开了我的应用程序,花了几秒钟才将其完全挂起,但是您可以看到在“ tick 7”和“ applicationDidEnterBackground”出现之后该应用程序停止运行。大约10秒钟后,我重新启动了该应用程序,这时您看到该应用程序恢复了活力,并在停止的位置继续滴答作响。
因此,如果您的应用仍在运行,则要么将其附加到Xcode调试器,要么可以使应用在后台运行。但是通常,当您离开应用程序时,该应用程序将被暂停,并且您会看到类似我上面概述的行为。
另外,有关使用统一日志记录,配置设备等的更多信息,请参阅WWDC 2016视频Unified Logging and Activity Tracing。