在应用程序进入暂停状态之前执行后台任务
问题描述:
我正试图在我的应用程序中执行有限长度的后台任务。但是,截至目前,我的代码在应用程序暂停之前未被执行。在应用程序进入暂停状态之前执行后台任务
我遵循了不少教程,声称以下是这种方式,但显然我得到了一些错误。相关代码应贴在下面(请只问任何澄清,如果我失去了一些东西):
class Manager {
private var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
init(){
// Add observer able of detecting when app will go to background
NotificationCenter.default.addObserver(self, selector: #selector(self.didEnterBackground(_:)), name: .UIApplicationDidEnterBackground, object: nil)
}
deinit {
// Observers removed when view controller is dismissed/deallocated
NotificationCenter.default.removeObserver(self)
}
// Routine performed when app will resign from active
@objc private func didEnterBackground(_ notification: Notification){
registerBackgroundTask()
// Code that needs to be executed before app is suspended ------
DispatchQueue.global().sync {
self.isBackgrounding = true
self.shutdownSession()
self.isConnected = false
self.isActivated = false
self.activate = false
self.connectionManager.closeConnectionToPeripherals()
}
// -----------------------------------------------------
self.endBackgroundTask()
}
func registerBackgroundTask() {
backgroundTask = UIApplication.shared.beginBackgroundTask { [weak self] in
self?.endBackgroundTask()
}
assert(backgroundTask != UIBackgroundTaskInvalid)
}
func endBackgroundTask() {
print("\n\n\nBackground task ended.\n\n\n")
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
}
我面临着一个问题,即后台任务似乎总是执行代码之前结束。如何在应用程序被暂停之前确保我的同步块中的代码得到执行?
我不太了解“registerBackgroundTask()” - 即使互联网坚持以这种方式实现 - 因为它调用了endBackgroundTask()。
答
您需要将self.endBackgroundTask()
呼叫转移到您的DispatchQueue区块,在self.connectionManager.closeConnectionToPeripherals()
之后。
registerBackgroundTask
方法不直接调用self.endBackgroundTask()
,而是仅在后台任务过期时调用。通常情况下,如果您的应用在后台〜30s后没有完成任务,就会发生这种情况。
我重新安排了您的建议的代码,但“后台任务结束”。仍然立即执行。我知道这个任务需要约。总共7秒,所以有些事情仍然是错误的。 它可能与我调用函数并因此被执行/启动但未在内部完成的事实有关吗? – matiastofteby
是的。如果您正在调用的函数正在执行异步工作,系统可能会在您返回之前冻结您的应用程序。如果这些函数需要是异步的,那么你必须通过传递一个完成块来修改它们,并在所有返回时立即执行'endBackgroundTask'。 – ersjoh