我有一种方法可以更改我的应用程序播放的音轨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)
当用户擦洗或向前/向后跳过时,此代码会更新锁定屏幕的已用时间。如果我将其注释掉,则nowPlayingInfo
更新setTrackNumber
在任何情况下都会按预期工作。
修改后的问题:当这两段代码都在主队列上运行时,它们是如何交互的?有什么办法可以nowPlayingInfo
更新,AVPlayerItemTimeJumpedNotification
因为当有电话时会有跳跃setTrackNumber
?