gpt4 book ai didi

swift - 当应用程序处于后台/非事件状态时,GCD `asyncAfter` 不启动

转载 作者:可可西里 更新时间:2023-11-01 01:21:06 26 4
gpt4 key购买 nike

我正在使用 AVAudioPlayer 播放唱片。在每个回放 session 之间我有 0 到 10 秒的间隔。为了制作这个间隔,我正在使用 AVAudioPlayerDelegate 并且播放完成后我将在延迟后开始新的播放:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
guard let session = playbackSessionId,
let audioTrack = audioTrack,
let failureHandler = playingFailure,
let successHandler = playingSuccess else {
playingFinished(flag, error: nil)
return
}
print("audioPlayerDidFinishPlaying fired")
DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + LoopInterval.currentInterval) { [weak self] in
print("asyncAfter fired")
guard let strongSelf = self,
let currentSession = strongSelf.playbackSessionId, session == currentSession else { return }
strongSelf.startPlayingRecordInLoop(audioTrack, success: successHandler, failure: failureHandler)
}
}

应用进入后台(home 按钮)后,audioPlayerDidFinishPlaying 触发,但 DispatchQueue.global(qos: .utility).asyncAfter不是。所以在控制台中我看到:

audioPlayerDidFinishPlaying 已触发

一旦应用程序激活,asyncAfter 就会触发,我会看到下一条日志消息:

asyncAfter 触发

当应用处于事件状态时,一切都按预期工作。

最佳答案

希望对大家有所帮助。我发现问题:当应用程序进入后台时,它会停止后台任务,并且仅在激活后才触发它们。为避免需要,您应该让您的应用在后台运行并等待长时间运行的后台任务。

backgroundTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: {
UIApplication.shared.endBackgroundTask(backgroundTaskID)
})

This method lets your app continue to run for a period of time after it transitions to the background. You should call this method at times where leaving a task unfinished might be detrimental to your app’s user experience. For example, your app could call this method to ensure that had enough time to transfer an important file to a remote server or at least attempt to make the transfer and note any errors. You should not use this method simply to keep your app running after it moves to the background.

任务完成后你应该调用endBackgroundTask。如果您在 backgroundTimeRemaining 变为 0 之前不结束后台任务,应用将被终止:

UIApplication.shared.endBackgroundTask(backgroundTaskID)

Each call to this method must be balanced by a matching call to the endBackgroundTask(:) method. Apps running background tasks have a finite amount of time in which to run them. (You can find out how much time is available using the backgroundTimeRemaining property.) If you do not call endBackgroundTask(:) for each task before time expires, the system kills the app. If you provide a block object in the handler parameter, the system calls your handler before time expires to give you a chance to end the task.

这就是我在我的案例中所做的:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
guard let session = playbackSessionId,
let audioTrack = audioTrack,
let failureHandler = playingFailure,
let successHandler = playingSuccess else {
playingFinished(flag, error: nil)
return
}
backgroundTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in
guard let taskId = self?.backgroundTaskID else { return }
UIApplication.shared.endBackgroundTask(taskId)
})
DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + LoopInterval.currentInterval) { [weak self] in
guard let strongSelf = self,
let currentSession = strongSelf.playbackSessionId, session == currentSession else { return }
strongSelf.startPlayingRecordInLoop(audioTrack, success: successHandler, failure: failureHandler)
if let backgroundTaskID = strongSelf.backgroundTaskID {
UIApplication.shared.endBackgroundTask(backgroundTaskID)
strongSelf.backgroundTaskID = nil
}
}
}

关于swift - 当应用程序处于后台/非事件状态时,GCD `asyncAfter` 不启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43873481/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com