[我的应用是使用AVAudioPlayer并具有Singleton模式和背景模式的音乐播放器。一切进展顺利,但是在我添加了用于锁定屏幕控制的命令中心后,发现了一种奇怪的行为。
当我在锁定屏幕上使用暂停/播放按钮时,有时可能会在后台创建额外的audioPlay共享实例,因为我发现重复打印的次数不止一次,例如在我的commandCenter.pauseCommand
代码中。并且音频已暂停或继续播放,但是接下来在应用程序的VC中单击命令中心按钮和播放/暂停按钮均无效。这是一个多线程问题,我在Swift中是一个新手,非常感谢您提供有关如何查找/解决此问题的帮助或提示。
/ / /命令中心和MPMediaItemProperty的代码
func setUpLockedScreenControl() {
// add control panel on locked screen
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.pauseCommand.isEnabled = true
commandCenter.playCommand.isEnabled = true
commandCenter.nextTrackCommand.isEnabled = true
commandCenter.previousTrackCommand.isEnabled = true
commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
SongData.isPlaying = false
AudioManager.sharedInstance.pauseMusic()
self.updateLockedScreenPlayingInfo()
print("pause music in command center")
self.playOrPauseButton.setImage(UIImage(named: "Play"), for: .normal)
self.playOrPauseButton.imageView?.contentMode = .scaleAspectFit
return .success
}
commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
SongData.isPlaying = true
AudioManager.sharedInstance.playMusic()
self.updateLockedScreenPlayingInfo()
print("play music in command center")
// add to continue update playing progress
self.playOrPauseButton.setImage(UIImage(named: "Pause"), for: .normal)
self.playOrPauseButton.imageView?.contentMode = .scaleAspectFit
return .success
}
commandCenter.nextTrackCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
self.goNextSong()
self.updateLockedScreenPlayingInfo()
return .success
}
commandCenter.previousTrackCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
self.goPreviousSong()
self.updateLockedScreenPlayingInfo()
return .success
}
}
func updateLockedScreenPlayingInfo() {
var info = Dictionary<String, Any>()
info[MPMediaItemPropertyTitle] = SongData.songList[SongData.currentTrack].songName
info[MPMediaItemPropertyAlbumTitle] = SongData.songList[SongData.currentTrack].albumName
info[MPMediaItemPropertyArtist] = SongData.songList[SongData.currentTrack].artistName
let image = SongData.songList[SongData.currentTrack].albumArtwork
let artwork = MPMediaItemArtwork.init(boundsSize: image.size, requestHandler: { (size) -> UIImage in
return image
})
info[MPMediaItemPropertyArtwork] = artwork
info[MPMediaItemPropertyPlaybackDuration] = AudioManager.sharedInstance.audioPlayer.duration
if SongData.isPlaying == true {
let time = AudioManager.sharedInstance.audioPlayer.currentTime
info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = time
info[MPMediaItemPropertyPlaybackDuration] = AudioManager.sharedInstance.audioPlayer.duration
info[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
print("SongData.isPlaying == true, current time is:", time)
} else {
let time = AudioManager.sharedInstance.audioPlayer.currentTime
info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = time
info[MPMediaItemPropertyPlaybackDuration] = AudioManager.sharedInstance.audioPlayer.duration
info[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
print("SongData.isPlaying == false, current time is:", time)
}
MPNowPlayingInfoCenter.default().nowPlayingInfo = info
}
/ / /这是发生错误时的控制台信息,在这种情况下,两次打印commandCenter.playCommand
代码
Playback OK
Session is Active
2019-10-23 11:38:06.331882+0800 LocalMusicPlayer[12366:853141] Can't end BackgroundTask: no background task exists with identifier 22 (0x16), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
SongData.isPlaying == true, current time is: 5.15344671201814
play music in command center
SongData.isPlaying == true, current time is: 5.155759637188209
play music in command center
/ / /在appDelegate中设置的背景模式,Can't end BackgroundTask
仅在iOS 13上出现,我认为这可能是苹果方面的问题。
func applicationWillResignActive(_ application: UIApplication) {
do {
// set options as empty [] could show control panel in locked screen.
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [])
print("Playback OK")
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
print(error)
}
}
/ / / AudioPlayer控件的Audio Manager.swift
class AudioManager: NSObject, AVAudioPlayerDelegate {
// use Singleton pattern keep the music continuing when user move through the App.
static let sharedInstance = AudioManager()
var audioPlayer: AVAudioPlayer!
var playingSong: SongData?
private override init() {
super.init()
}
... ...
}
问题很可能是您的setUpLockedScreenControl
被意外调用了两次。因此,您将目标添加了两次,并且在锁定屏幕中的点击两次发送了它的消息。