尽管启用了后台功能,计时器仍然停止
Timer stops despite background capability is enabled
我正在使用 AVAudioPlayer
播放循环声音。我当前的代码有这一行: audioPlayer.numberOfLoops = -1
,这会导致无限循环。我使用定时器在一段时间后停止循环播放音频。这在应用程序位于前台时有效,但在它进入后台后无效。
我的应用程序的后台功能是:
尽管启用了后台模式并且在应用程序进入后台时正在播放音频,但应用程序似乎在调用 applicationDidEnterBackground
后立即暂停。我这么说是因为 (1) 定时器停止每秒向控制台打印输出 (2) 即使定时器应该结束,音频也会无限期地播放。
我读过 here 一定不是这种情况,如果在后台播放音频,应用程序不应暂停,但在我的应用程序中似乎不是这种情况。
我在这里错过了什么?我应该怎么做才能让计时器真正在后台 运行,除了播放循环声音(如果不够用)?
运行音频的代码:
var audioPlayer = AVAudioPlayer()
do {
let (fileName, fileExtension) = fileNameExtension(fileName: soundFileName)
let soundURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: fileName, ofType: fileExtension)!)
audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
audioPlayer.prepareToPlay()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .default, options: [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP, .mixWithOthers])
try AVAudioSession.sharedInstance().setActive(true)
} catch let error as NSError {
print("Fetch error: \(error) description: \(error.userInfo)")
}
} catch let error as NSError {
print("Fetch error: \(error) description: \(error.userInfo)")
}
audioPlayer.numberOfLoops = -1
audioPlayer.play()
运行 定时器的代码。此代码 运行s 当应用程序在前台时。:
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in
self?.updateTimer()
})
RunLoop.current.add(timer, forMode: .common)
timer.tolerance = 0.2
更新定时器:
@objc func updateTimer() {
remainingTime -= 1
if remainingTime <= 0.0 {
complete()
}
}
这个问题有一些错误的前提:
applicationDidEnterBackground
并不意味着您的应用将被暂停。 通常 会,但是如果您有音频后台模式功能和 playback
音频类别,并且当您进入后台时正在播放声音,您就不会被挂起;相反,你 运行 在后台。
在您进入后台之前启动的计时器 在这种情况下在后台工作。
因此,如果您在应用程序的背景中听到声音,但您的计时器 没有 触发,那一定是由于您正在做的其他事情。也许您已经配置了一些东西,以便在您进入后台时计时器失效?
我正在使用 AVAudioPlayer
播放循环声音。我当前的代码有这一行: audioPlayer.numberOfLoops = -1
,这会导致无限循环。我使用定时器在一段时间后停止循环播放音频。这在应用程序位于前台时有效,但在它进入后台后无效。
我的应用程序的后台功能是:
尽管启用了后台模式并且在应用程序进入后台时正在播放音频,但应用程序似乎在调用 applicationDidEnterBackground
后立即暂停。我这么说是因为 (1) 定时器停止每秒向控制台打印输出 (2) 即使定时器应该结束,音频也会无限期地播放。
我读过 here 一定不是这种情况,如果在后台播放音频,应用程序不应暂停,但在我的应用程序中似乎不是这种情况。
我在这里错过了什么?我应该怎么做才能让计时器真正在后台 运行,除了播放循环声音(如果不够用)?
运行音频的代码:
var audioPlayer = AVAudioPlayer()
do {
let (fileName, fileExtension) = fileNameExtension(fileName: soundFileName)
let soundURL = URL.init(fileURLWithPath: Bundle.main.path(forResource: fileName, ofType: fileExtension)!)
audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
audioPlayer.prepareToPlay()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .default, options: [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP, .mixWithOthers])
try AVAudioSession.sharedInstance().setActive(true)
} catch let error as NSError {
print("Fetch error: \(error) description: \(error.userInfo)")
}
} catch let error as NSError {
print("Fetch error: \(error) description: \(error.userInfo)")
}
audioPlayer.numberOfLoops = -1
audioPlayer.play()
运行 定时器的代码。此代码 运行s 当应用程序在前台时。:
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] _ in
self?.updateTimer()
})
RunLoop.current.add(timer, forMode: .common)
timer.tolerance = 0.2
更新定时器:
@objc func updateTimer() {
remainingTime -= 1
if remainingTime <= 0.0 {
complete()
}
}
这个问题有一些错误的前提:
applicationDidEnterBackground
并不意味着您的应用将被暂停。 通常 会,但是如果您有音频后台模式功能和playback
音频类别,并且当您进入后台时正在播放声音,您就不会被挂起;相反,你 运行 在后台。在您进入后台之前启动的计时器 在这种情况下在后台工作。
因此,如果您在应用程序的背景中听到声音,但您的计时器 没有 触发,那一定是由于您正在做的其他事情。也许您已经配置了一些东西,以便在您进入后台时计时器失效?