web-dev-qa-db-fra.com

Pas de délégué AVPlayer? Comment suivre quand la chanson a fini de jouer? Développement iPhone Objective C

J'ai regardé autour de moi mais je ne trouve pas de protocole de délégué pour le AVPlayer class. Ce qui donne?

J'utilise sa sous-classe, AVQueuePlayer, pour lire un tableau de AVPlayerItems, chacun chargé à partir d'une URL. Existe-t-il un moyen de faire appel à une méthode à la fin d'une chanson? Notamment à la fin de la file d'attente?

Et si cela n’est pas possible, puis-je appeler une méthode lorsque la chanson commence à jouer, après la mise en mémoire tampon? J'essaie d'obtenir une icône de chargement mais cette icône est désactivée avant que la musique ne commence réellement, même si c'est après le [audioPlayer play] action.

83
Tyler

Oui, la classe AVPlayer n'a pas de protocole de délégué comme AVAudioPlayer. Vous devez vous abonner aux notifications sur un AVPlayerItem. Vous pouvez créer un AVPlayerItem en utilisant la même URL que celle que vous auriez sinon transmise à -initWithURL: sur 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
}
149
arexx

Oui. Ajouter un observateur KVO au statut ou à la cote du joueur:

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

Donc, fondamentalement, c'est tout.

Disclaimer: J'ai écrit ça ici, donc je n'ai pas vérifié si le code était bon. AUSSI je n'ai jamais utilisé AVPlayer auparavant, mais cela devrait être à peu près correct.

8
Daij-Djan

Swift - J'ajoute un observateur à AVPlayerItem à chaque fois que j'ajoute une vidéo au lecteur:

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
}
5
budidino

Il y a beaucoup d’informations dans le Apple docs Guide de programmation AVFoundation (recherchez la section de lecture de contrôle). Il semble que ce soit principalement via KVO. rafraîchissez-vous si vous n'êtes pas trop familier (il existe un guide pour cela Key Value Observer ProgrammingGuide .

1
Paul.s

J'utilise celui-ci, et ça marche:

_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 est ma classe personnalisée avec quelques propriétés et timeObserver est id ivar.

1
Timur Mustafaev