2011-09-14 61 views
15

我有一个使用AVPlayer构建的音频播放器。AVPlayer replaceCurrentItemWithPlayerItem无法在iOS 4.3.3+上工作

目前,我把player实例周围,当我需要换轨(无论是从手动选择或轨道已经到达末端),我创建了一个新的AVPlayerItem和我打电话replaceCurrentItemWithPlayerItem新项目。

根据文档,replaceCurrentItemWithPlayerItem是一个异步操作,所以我也观察了播放器的关键路径当前项目。当被调用时,我会告诉我的玩家玩。

下面是相关代码:

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]; 
} 

这里是键值观察回调:

- (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]; 
    } 
} 

在iOS 4.3.3(和iOS 5)我的重点观察方法被调用,但_player.currentItem总是nil。在4.2.1和4.3.2上,该属性包含实际值。这种方法不会再被调用。所以从本质上来说,替换似乎总是失败。

这看起来像一个错误,但也许我做错了什么。

+0

Dunja解答了您的问题吗? –

回答

17

我在iOS 5(包括5.0.1)中遇到了这个问题。它曾经在iOS 4.x上正常工作。

有两种方法可以解决这个问题,每次需要交换音轨时,发布并重新创建AVPlayer和期望的AVPlayerItem。或者,只需在主线程上拨打replaceCurrentItemWithPlayerItem:即可。

我试过这两个选项,他们工作得很好。

积分:Apple Developer Forums

+0

在主线程上运行修复了我的bug。 – vaughan

1

我一直在遇到类似的问题。你可能像我一样从AVPlayerDemoPlaybackViewController from Apple sample code开始。也许问题是为什么currentItemnil是因为它尚未加载或准备播放(我的问题是我无法获得新的AVPlayerItem的持续时间)。

currentItem的观察状态为ReadyToPlay时,您可以尝试开始播放。

AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; 
    switch (status) { 
     case AVPlayerStatusUnknown: { 
      NSLog(@"PLAYER StatusUnknown"); 
     } 
      break; 
     case AVPlayerStatusReadyToPlay: { 
      NSLog(@"PLAYER ReadyToPlay"); 
      [self play]; 
     } 
      break; 
     case AVPlayerStatusFailed: { 
      AVPlayerItem *playerItem = (AVPlayerItem *)object; 
      [self handleError: [playerItem.error localizedDescription]]; 
     } 
      break; 
    } 

我不知道这是否会铁锅你,我没有尝试这种在低于或高于4.3.4的iPad高,所以我想我会很快遇到并发症。