AVPlayer replaceCurrentItemWithPlayerItem not working on iOS 4.3.3+

avplayer, ios, objective-c

Solution

I had this issue with iOS 5 (including 5.0.1). It used to work fine on iOS 4.x.

There are two ways to workaround this, release and recreate your `AVPlayer` with the desired `AVPlayerItem`s each time you need to swap tracks. Or, simply call `replaceCurrentItemWithPlayerItem:` on the main thread.

I tried both options and they worked fine.

Credits to: Apple Developer Forums

Problem

I have an audio player that I'm building using AVPlayer. Currently, I keep the `player` instance around and when I need to swap tracks (either from a manual selection or the track has reached the end) I create a new `AVPlayerItem` and I call `replaceCurrentItemWithPlayerItem` with the new item. According to the docs, `replaceCurrentItemWithPlayerItem` is an asynchronous operation, so I also observe the currentItem key path of the player. When that gets called, I tell my player to play. Here is the relevant code: ``` AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset]; [playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:CHStreamingAudioPlayer_PlayerItemStatusChangedContext]; if (!_player) { _player = [[AVPlayer alloc] initWithPlayerItem:playerItem]; [_player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:CHStreamingAudioPlayer_PlayerStatusChangedContext]; [_player addObserver:self forKeyPath:@"currentItem" options:NSKeyValueObservingOptionNew context:CHStreamingAudioPlayer_PlayerCurrentItemChangedContext]; } else { [_player replaceCurrentItemWithPlayerItem:playerItem]; } ``` And here is the key value observation callback: ``` - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == CHStreamingAudioPlayer_PlayerCurrentItemChangedContext) { NSLog(@"Player's current item changed! Change dictionary: %@", change); if (_player.currentItem) { [self play]; //<---- doesn't get called } } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } ``` On iOS 4.3.3 (and iOS 5) my key observation method is called but `_player.currentItem` is always `nil`. On 4.2.1 and 4.3.2 this property contains the actual value. This method is never called again. So in essence, replacing seems to always fail. This seems like a bug, but perhaps I'm doing something wrong.

Original source