关于kvo的使用不是本文的讨论范围,本文主要讲一下业务复杂的情况下,kvo的observer管理[add/remove]。 ####使用场景 一个AVQueuePayer的播放器,面对多个AVPlayerItem,对于currentItem一些属性的监视,如何做了,且看看我的方案吧。
规则:在这样一个Queue中有能播放的,有失败的,若一个Item失败,播放下一个,只到最后一个Item终止。
1.[player advancetoNextItem]之前移除currentItem的observer,之后增加currentItem的observer
[self removeCurrentPlayerItemObserver:self.player.currentItem];
[player advancetoNextItem];
[self addCurrentPlayerItemObserver:self.player.currentItem];
- (void)addCurrentPlayerItemObserver:(AVPlayerItem *)playerItem {
[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)removeCurrentPlayerItemObserver:(AVPlayerItem *)playerItem {
[playerItem removeObserver:self forKeyPath:@"status"];
[playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
[playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
}
复制代码
上述的代码且不说严谨什么问题,对于observer的add/remove请按照成对调用,多了崩溃,少了也会崩溃。而这儿对于currentItem的的observer add/remove时,时机在播放流程正常的情况下是一番风顺,对于网络不好,播放地址服务器导致失败的,会出现当前item的observer移除失败。故有了下面的方案
增加
对于增加了observer的AVPlayerItem把他塞到这样一个数组里面
1.数组里若有则不再add observer
移除observer
对于AVPQueuePlayer我们只要保证currentItem有observer就好,所以移除时,我们直接对整个数组实例的observer移除。
复制代码
show me code
/** 调用这两个方法即可*/
- (void)addPlayerItemObserver:(nonnull AVPlayerItem *)playerItem;
- (void)removePlayerItemsObser;
- (void)addCurrentPlayerItemObserver:(nonnull AVPlayerItem *)playerItem;
- (void)removeCurrentPlayerItemObserver:(nonnull AVPlayerItem *)playerItem;
复制代码
- (void)addPlayerItemObserver:(nonnull AVPlayerItem *)playerItem {
if(playerItem == nil) {
return;
}
NSInteger index = -1;
for(AVPlayerItem * tmPlayerItem in self.addObserverPlayerItems) {
if(tmPlayerItem == playerItem) {
index = 0;
break;
}
}
if(index < 0) {
[self addCurrentPlayerItemObserver:playerItem];
[self.addObserverPlayerItems addObject:playerItem];
}
}
- (void)removePlayerItemsObser {
for(AVPlayerItem * playerItem in self.addObserverPlayerItems) {
[self removeCurrentPlayerItemObserver:playerItem];
}
[self.addObserverPlayerItems removeAllObjects];
}
- (void)addCurrentPlayerItemObserver:(AVPlayerItem *)playerItem {
[playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
[playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)removeCurrentPlayerItemObserver:(AVPlayerItem *)playerItem {
[playerItem removeObserver:self forKeyPath:@"status"];
[playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
[playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
[playerItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
}
复制代码
注:时光不老,陪伴我们的最终是什么,存在的意义又是如何,愿留下些许感动,还好有你~ (胡言乱语)