我有一个方法可以更改我的应用程序的AVPlayer
播放的音频轨道,并为新轨道设置MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo
:
func setTrackNumber(trackNum: Int) {
self.trackNum = trackNum
player.replaceCurrentItemWithPlayerItem(tracks[trackNum])
var nowPlayingInfo: [String: AnyObject] = [ : ]
nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = tracks[trackNum].albumTitle
nowPlayingInfo[MPMediaItemPropertyTitle] = "Track \(trackNum)"
...
MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = nowPlayingInfo
print("Now playing local: \(nowPlayingInfo)")
print("Now playing lock screen: \(MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo)")
}
我在用户明确选择专辑或曲目以及曲目结束且下一首自动开始时调用此方法。 当用户设置专辑或曲目时,锁屏正确显示曲目元数据,但是当曲目结束并自动设置下一首曲目时,则不会显示。
我添加了打印语句以确保正确填充nowPlayingInfo字典。 如预期所示,当此方法由用户发起的专辑或曲目更改调用时,两个打印语句打印相同的字典内容。 但是,在自动曲目更改后调用该方法的情况下,本地nowPlayingInfo变量显示新的trackNum,而MPNowPlayingInfoCenter.defaultCenter()。nowPlayingInfo显示先前的trackNum:
Now playing local: ["title": Track 9, "albumTitle": Test Album, ...]
Now playing set: Optional(["title": Track 8, "albumTitle": Test Album, ...]
我发现当我在设置MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo
为nowPlayingInfo
的那一行设置断点时,歌曲编号会正确地更新到锁屏界面。在该行下方添加sleep(1)
也能确保锁屏界面上的歌曲得到正确更新。
我已经验证了nowPlayingInfo
始终是从主队列设置的。我尝试显式地将此代码在主队列或其他队列中运行,但行为没有变化。
是什么阻止了我对MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo
的更改?如何确保设置MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo
始终更新锁屏信息?
编辑
第N次检查代码后,我想到了“并发”,找出了罪魁祸首。我不知道为什么之前没有怀疑过这个:
func playerTimeJumped() {
let currentTime = currentItem().currentTime()
dispatch_async(dispatch_get_main_queue()) {
MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo?[MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds(currentTime)
}
}
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "playerTimeJumped",
name: AVPlayerItemTimeJumpedNotification,
object: nil)
这段代码在用户快进/倒退时更新锁屏的已过时间。如果将其注释掉,则在任何情况下,从setTrackNumber获取的nowPlayingInfo更新都能按预期工作。
修订后的问题:当它们都在主队列上运行时,这两个代码片段是如何交互的?是否有任何方法可以在AVPlayerItemTimeJumpedNotification上进行nowPlayingInfo更新,假设在调用setTrackNumber时会发生跳跃?
nowPlayingInfo
可能是异步完成的,因此打印输出并不是很有帮助。但我期望设置会在某个时刻完成!当手机显示锁屏界面时,我知道setTrackNumber
总是被调用的,因为我的调试打印信息出现在控制台上。 - Hélène Martin