AVPlayer replaceCurrentItemWithPlayerItem не работает на iOS 4.3.3+ - PullRequest
15 голосов
/ 14 сентября 2011

У меня есть аудиоплеер, который я собираю с помощью AVPlayer.

В настоящее время я сохраняю экземпляр player, и когда мне нужно поменять местами треки (либо из ручного выбора, либо до того, как трек достиг конца), я создаю новый AVPlayerItem и вызываю replaceCurrentItemWithPlayerItem с новым пункт.

Согласно документации, replaceCurrentItemWithPlayerItem - это асинхронная операция, поэтому я также наблюдаю путь ключа игрока currentItem . Когда это вызвано, я говорю своему игроку играть.

Вот соответствующий код:

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 это свойство содержит фактическое значение. Этот метод никогда не вызывается снова. Так что, по сути, замена кажется неудачной.

Это похоже на ошибку, но, возможно, я делаю что-то не так.

Ответы [ 2 ]

17 голосов
/ 04 марта 2012

У меня была эта проблема с iOS 5 (включая 5.0.1). Раньше нормально работал на iOS 4.x.

Есть два способа обойти это, отпустить и воссоздать ваши AVPlayer с нужными AVPlayerItem с каждый раз, когда вам нужно поменять дорожки. Или просто позвоните replaceCurrentItemWithPlayerItem: в главном потоке.

Я пробовал оба варианта, и они работали нормально.

Кредиты для: Форумы разработчиков Apple

1 голос
/ 05 октября 2011

У меня были похожие проблемы. Вы, вероятно, начали с AVPlayerDemoPlaybackViewController из примера Apple , как я. Возможно, проблема в том, почему currentItem равен nil, потому что он еще не загружен или не готов к воспроизведению (моя проблема заключалась в том, что я не смог получить продолжительность нового 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;
    }

Я не знаю, сработает ли это для вас, я не пробовал это на iPad ниже или выше, чем 4.3.4, поэтому, думаю, скоро у меня возникнут сложности.

...