没有 AVPlayer 委托? 如何跟踪歌曲播放完毕? 目标 C iPhone 开发

我到处找过了,但找不到 AVPlayer class的授权协议,怎么回事?

我使用它的子类 AVQueuePlayer来播放 AVPlayerItems的数组,每个数组都是从 URL 加载的。有没有什么方法可以在一首歌播放完毕后调用一个方法?尤其是在队伍的最后?

如果这是不可能的,有没有办法,我可以调用一个方法时,歌曲开始播放,后缓冲?我试图得到一个载入图标在那里,但它关闭图标之前,音乐实际开始,即使它是在 [audioPlayer play]的行动。

64375 次浏览

There is a lot of information in the Apple docs AVFoundation Programming Guide (look for the monitoring playback section). It appears to be mainly through KVO so you may wish to brush up on that if you are not too familiar (there is a guide for that to Key Value Observing ProgrammingGuide.

Yes. Add a KVO observer to the player's status or rate:

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

So basically, that's it.

Disclaimer: I wrote that in here so I didn't check if the code was good. ALSO I never used AVPlayer before but it should be about right.

Yes, the AVPlayer class does not have a delegate protocol like the AVAudioPlayer. You need to subscribe to notifications on an AVPlayerItem. You can create an AVPlayerItem using the same URL that you would otherwise pass to -initWithURL: on 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
}

I'm using this one, and it works:

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

where _playingAudio is my custom class with some properties and timeObserver is id ivar.

Swift 3 - I add an observer to AVPlayerItem every time I add a video to the player:

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
}