Nessun delegato AVPlayer? Come tenere traccia del termine della riproduzione del brano? Obiettivo C sviluppo iPhone


84

Mi sono guardato intorno ma non riesco a trovare un protocollo delegato per AVPlayer class . Cosa succede?

Sto usando la sua sottoclasse,, AVQueuePlayerper riprodurre un array di AVPlayerItems, ciascuno caricato da un URL. C'è un modo per chiamare un metodo quando finisce la riproduzione di una canzone? In particolare alla fine della coda?

E se ciò non è possibile, c'è un modo per chiamare un metodo quando la canzone INIZIA a suonare, dopo il buffering? Sto cercando di inserire un'icona di caricamento lì, ma spegne l'icona prima che la musica inizi effettivamente, anche se è dopo l' [audioPlayer play]azione.

Risposte:


152

Sì, la classe AVPlayer non dispone di un protocollo delegato come AVAudioPlayer. Devi iscriverti alle notifiche su un AVPlayerItem. Puoi creare un AVPlayerItem utilizzando lo stesso URL che altrimenti -initWithURL:passeresti su 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
Assicurati di usare itemDidFinishPlaying:, ad esempio, con i due punti. Dalla NSNotificationCenterdocumentazione: il metodo specificato da notificationSelector deve avere uno e un solo argomento (un'istanza di NSNotification).
Rudolf Adamkovič

@RudolfAdamkovic Grazie per la nota - Ho modificato la mia risposta di conseguenza.
arexx

8

Sì. Aggiungi un osservatore KVO allo stato o al tasso del giocatore:

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

Quindi, fondamentalmente, è così.

Disclaimer: l'ho scritto qui quindi non ho controllato se il codice era buono. INOLTRE non ho mai usato AVPlayer prima, ma dovrebbe essere giusto.


Come rimuovere l'osservatore @ "rate"?
Saumil Shah

Mi è stato detto in una modifica che devo osservare con certezza la velocità. adattato
Daij-Djan

4
Un problema con questo approccio è che penserà che una pausa sia la fine della musica. Il tasso in pausa è zero come sarebbe alla fine.
C6Silver

5

Swift 3 : aggiungo un osservatore AVPlayerItemogni volta che aggiungo un video al lettore:

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

Ci sono molte informazioni nella Guida alla programmazione AVFoundation di documenti Apple (cerca la sezione di riproduzione del monitoraggio). Sembra che sia principalmente attraverso KVO, quindi potresti voler rispolverare questo se non sei troppo familiare (c'è una guida per questo a Key Value Observing ProgrammingGuide .


4
Grazie, prima l'ho fatto funzionare monitorando il tempo tramite KVO, ma poi ho implementato AVPlayerItemDidPlayToEndTimeNotification poiché è più pulito e richiede meno processore.
Tyler

1
Un po 'un mix pazzo di NSNotificationCenter, KVO e basato su blocchi lì dentro. Prendi la tua mente Apple!
CupawnTae

1

Sto usando questo e funziona:

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

dov'è la _playingAudiomia classe personalizzata con alcune proprietà ed timeObserverè idivar.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.