// Register with the notification center after creating the player item.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:<#The player item#>];
- (void)playerItemDidReachEnd:(NSNotification *)notification {
[player seekToTime:kCMTimeZero];
}
播放多个AVPlayerItem
可以使用AVQueuePlayer对象顺序播放多个 AVPlayerItem. AVQueuePlayer类是AVPlayer的一个子类. 可以使用一个 player items 的数组来初始化一个 queue player:
NSArray *items = <#An array of player items#>;
AVQueuePlayer *queuePlayer = [[AVQueuePlayer alloc] initWithItems:items];
接下来可以像使用 AVPlayer 对象一样发送play消息开始播放 player items. queue player 依次播放每个 item, 如果需要跳到下一个 item, 可以向 queue player 发送advanceToNextItem消息.
AVPlayerItem *anItem = <#Get a player item#>;
if ([queuePlayer canInsertItem:anItem afterItem:nil]) {
[queuePlayer insertItem:anItem afterItem:nil];
}
监听播放
可以监听包括播放状态以及正在被播放的 player item 在内的许多方面的信息. 当状态变化不可控时, 这一点十分有用. 例如:
当用户切换的其他应用时, player 的 rate 将会降至 0.0
如果正在播放远程媒体, player 的loadedTimeRanges和loadedTimeRanges属性将会随着数据的加载而变化
播放 HTTP 流媒体时, 一个 player 的currentItem属性会被自动创建.
播放 HTTP 流媒体时, 一个 player 的tracks属性可能会随着播放而变化
由于某些原因导致播放失败时, 一个 player 或者 item 的status属性会随之变化
可以使用 KVO 来监听这些属性的变化.
响应播放状态的改变
当一个 player 或者 item 的状态发生改变时, 会发出对应 KVO 变化的 notification. 如果一个资源因为某些原因不能播放, status 会变为AVPlayerStatusFailed或者AVPlayerItemStatusFailed. 这种情况下, error对象会包含相关的错误信息.
AV Foundation 并不会指定 notification 发出的线程. 如果需要更新 UI, 你必须手动切换到主线程. 下面是使用dispatch_async切换到主线程的示例代码:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {
if (context == <#Player status context#>) {
AVPlayer *thePlayer = (AVPlayer *)object;
if ([thePlayer status] == AVPlayerStatusFailed) {
NSError *error = [<#The AVPlayer object#> error];
// Respond to error: for example, display an alert sheet.
return;
}
// Deal with other status change if appropriate.
}
// Deal with other change notifications if appropriate.
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
return;
}
在 completion block 中创建 AVPlayerItem, 并设置 player view 的 player.
// Define this constant for the key-value observation context.
static const NSString *ItemStatusContext;
// Completion handler block.
dispatch_async(dispatch_get_main_queue(),
^{
NSError *error;
AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];
if (status == AVKeyValueStatusLoaded) {
self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
// ensure that this is done before the playerItem is associated with the player
[self.playerItem addObserver:self forKeyPath:@"status"
options:NSKeyValueObservingOptionInitial context:&ItemStatusContext];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.playerItem];
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
[self.playerView setPlayer:self.player];
}
else {
// You should deal with the error appropriately.
NSLog(@"The asset's tracks were not loaded:\n%@", [error localizedDescription]);
}
});
// Register with the notification center after creating the player item.
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[self.player currentItem]];
- (void)playerItemDidReachEnd:(NSNotification *)notification {
[self.player seekToTime:kCMTimeZero];
}