MPNowPlayingInfoCenter nowPlayingInfo not updating at end of track
<p>I have a method that changes the audio track played by my app's <code>AVPlayer</code> and also sets <code>MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo</code> for the new track:</p>

<pre><code>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)")   
}
</code></pre>

<p>I call this method when the user explicitly selects an album or track and when a track ends and the next one automatically starts.  The lock screen correctly shows the track metadata when the user sets an album or track but NOT when a track ends and the next one is automatically set.</p>

<p>I added print statements to make sure  I was correctly populating the <code>nowPlayingInfo</code> dictionary.  As expected, the two print statements print the same dictionary content when this method is called for a user-initiated change of album or track.  However, in the case when the method is called after an automatic track change, the local <code>nowPlayingInfo</code> variable shows the new <code>trackNum</code> whereas <code>MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo</code> shows the previous <code>trackNum</code>:</p>

<pre><code>Now playing local: ["title": Track 9, "albumTitle": Test Album, ...]
Now playing set: Optional(["title": Track 8, "albumTitle": Test Album, ...]
</code></pre>

<p>I discovered that when I set a breakpoint on the line that sets <code>MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo</code> to <code>nowPlayingInfo</code>, then the track number is correctly updated on the lock screen.  Adding <code>sleep(1)</code> right after that line also ensures that the track on the lock screen is correctly updated.</p>

<p>I have verified that <code>nowPlayingInfo</code> is always set from the main queue.  I've tried explicitly running this code in the main queue or in a different queue with no change in behavior.</p>

<p>What is preventing my change to <code>MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo</code>? How can I make sure that setting <code>MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo</code> always updates the lock screen info?</p>

<p><strong>EDIT</strong></p>

<p>After going through the code for the Nth time thinking "concurrency", I've found the culprit. I don't know why I didn't get suspicious about this earlier:</p>

<pre><code>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)
</code></pre>

<p>This code updates the lock screen's time elapsed when the user scrubs or skips forward/back. If I comment it out, the <code>nowPlayingInfo</code> update from <code>setTrackNumber</code> works as expected under any condition.</p>

<p><strong>Revised questions</strong>: how are these two pieces of code interacting when they're both run on the main queue? Is there any way I can do a <code>nowPlayingInfo</code> update on <code>AVPlayerItemTimeJumpedNotification</code> given that there will be a jump when there's a call on <code>setTrackNumber</code>?</p>