Немає представника AVPlayer? Як відстежити, коли пісня закінчилася? Завдання C Розробка iPhone


84

Я озирнувся, але не можу знайти протокол делегування для AVPlayer class. Що дає?

Я використовую його підклас,, AVQueuePlayerдля відтворення масиву AVPlayerItems, кожен завантажений з URL-адреси. Чи є спосіб назвати метод, коли пісня закінчується? Помітно в кінці черги?

І якщо це неможливо, чи є спосіб, яким би я міг викликати метод, коли пісня ЗАПУСКУЄ, після буферизації? Я намагаюся отримати там значок завантаження, але він вимикає значок перед тим, як музика насправді починається, хоча це і після [audioPlayer play]дії.

Відповіді:


152

Так, клас AVPlayer не має протоколу делегування, як AVAudioPlayer. Вам потрібно підписатися на сповіщення на AVPlayerItem. Ви можете створити AVPlayerItem, використовуючи ту саму URL-адресу, що інакше переходили б до -initWithURL:AVPlayer.

-(void)startPlaybackForItemWithURL:(NSURL*)url {

    // First create an AVPlayerItem
    AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:url];

    // Subscribe to the AVPlayerItem's DidPlayToEndTime notification.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem];

    // Pass the AVPlayerItem to a new player
    AVPlayer* player = [[[AVPlayer alloc] initWithPlayerItem:playerItem] autorelease];

    // Begin playback
    [player play]

} 

-(void)itemDidFinishPlaying:(NSNotification *) notification {
    // Will be called when AVPlayer finishes playing playerItem
}

1
Обов’язково застосовуйте itemDidFinishPlaying:, наприклад, з товстою кишкою. З NSNotificationCenterдокументації: Метод, зазначений notificationSelector, повинен мати один і лише один аргумент (екземпляр NSNotification).
Рудольф Адамкович

@RudolfAdamkovic Дякую за примітку - я відповідним чином відредагував свою відповідь.
arexx

8

Так. Додайте спостерігача KVO до статусу або рейтингу гравця:

- (IBAction)go {
   self.player = .....
   self.player.actionAtItemEnd = AVPlayerActionStop;
   [self.player addObserver:self forKeyPath:@"rate" options:0 context:0]; 
}

- (void)stopped {
    ...
    [self.player removeObserver:self]; //assumes we are the only observer
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (context == 0) {
        if(player.rate==0.0) //stopped
            [self stopped];
    }
    else
        [super observeVal...];
}

Отже, в основному, все.

Застереження: я писав це тут, тому не перевіряв, чи правильний код. ТАКОЖ я ніколи раніше не використовував AVPlayer, але це повинно бути приблизно правильно.


Як видалити спостерігача @ "rate"?
Сауміл Шах,

Мені сказали в редагуванні, що мені потрібно точно дотримуватися норми. адаптоване
Daij-Djan

4
Проблема такого підходу полягає в тому, що він буде думати, що пауза - це кінець музики. Швидкість при паузі дорівнює нулю, як і в кінці.
C6Silver

5

Свіфт 3 - я додаю спостерігача AVPlayerItemкожного разу, коли додаю відео на плеєр:

func playVideo(url: URL) {
  let playerItem = AVPlayerItem(asset: AVURLAsset(url: someVideoUrl))
  NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidPlayToEndTime), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem)
  self.player.replaceCurrentItem(with: playerItem)
  self.player.play()
}

func playerItemDidPlayToEndTime() {
  // load next video or something
}

1

У посібнику з програмування програм AVFoundation від Apple docs багато інформації (шукайте розділ відтворення моніторингу). Здається, це в основному через KVO, тому, можливо, ви захочете розглянути це, якщо ви не надто знайомі (для цього є посібник із спостереження за ключовими значеннями ProgrammingGuide .


4
Дякую, спочатку я змусив його працювати, контролюючи час за допомогою KVO, але потім я застосував AVPlayerItemDidPlayToEndTimeNotification, оскільки він чистіший і менш трудомісткий.
Тайлер

1
Трохи божевільна суміш NSNotificationCenter, KVO та блокової бази. Вирішіть Apple!
CupawnTee

1

Я використовую цей, і він працює:

_player = [[AVPlayer alloc]initWithURL:[NSURL URLWithString:_playingAudio.url]];
CMTime endTime = CMTimeMakeWithSeconds(_playingAudio.duration, 1);
timeObserver = [_player addBoundaryTimeObserverForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:endTime]] queue:NULL usingBlock:^(void) {
    [_player removeTimeObserver:timeObserver];
    timeObserver = nil;
    //TODO play next sound
}];
[self play];

де _playingAudioмій власний клас з деякими властивостями, і timeObserverє idivar.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.