美文网首页
KVO(观察者模式)

KVO(观察者模式)

作者: 韩吉_ | 来源:发表于2016-08-22 08:42 被阅读113次

    一、简介

    KVO,是Key-Value Observing的缩写,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。每次指定的被观察的对象的属性被修改后,KVO自动通知相应的观察者。

    二、示范举例

    因为我是在研究视频播放的时候研究的,所以这里以监听AVPlayer的状态值为例:
    首先定义属性

    @property (nonatomic ,strong) AVPlayer *player;
    @property (nonatomic ,strong) AVPlayerItem *playerItem;
    

    然后在viewDidLoad中对playItem的status和loadedTimeRanges这两个属性进行了监听

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        NSURL *videoUrl = [NSURL URLWithString:@"http://v.jxvdy.com/sendfile/w5bgP3A8JgiQQo5l0hvoNGE2H16WbN09X-ONHPq3P3C1BISgf7C-qVs6_c8oaw3zKScO78I--b0BGFBRxlpw13sf2e54QA"];
        self.playerItem = [AVPlayerItem playerItemWithURL:videoUrl];
        [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];// 监听status属性
        [self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性
        self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
        self.playerView.player = _player;
        self.stateButton.enabled = NO;
    
    }
    

    然后对监听方法进行了实现:
    只要监听的属性值发生了改变就会调用监听方法,这里我在方法中做了一个判断,判断当前发生改变的监听属性是status还是loadedTimeRanges,然后就可以在方法中实现监听属性发生改变时想要实现的效果了。

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        AVPlayerItem *playerItem = (AVPlayerItem *)object;
        if ([keyPath isEqualToString:@"status"]) {
            if ([playerItem status] == AVPlayerStatusReadyToPlay) {
                NSLog(@"AVPlayerStatusReadyToPlay");
                self.stateButton.enabled = YES;
                CMTime duration = self.playerItem.duration;// 获取视频总长度
                CGFloat totalSecond = playerItem.duration.value / playerItem.duration.timescale;// 转换成秒
                _totalTime = [self convertTime:totalSecond];// 转换成播放时间
                [self customVideoSlider:duration];// 自定义UISlider外观
                NSLog(@"movie total duration:%f",CMTimeGetSeconds(duration));
                [self monitoringPlayback:self.playerItem];// 监听播放状态
            } else if ([playerItem status] == AVPlayerStatusFailed) {
                NSLog(@"AVPlayerStatusFailed");
            }
        } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
            NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
            NSLog(@"Time Interval:%f",timeInterval);
            CMTime duration = _playerItem.duration;
            CGFloat totalDuration = CMTimeGetSeconds(duration);
            [self.videoProgress setProgress:timeInterval / totalDuration animated:YES];
        }
    }
    

    尤其要注意的的一点是,KVO在使用之后还有一步必须要进行的操作,就是释放添加的观察者,无论是在MRC还是在ARC中,这是一定要进行的一步操作,不然就会引起crash。

    - (void)dealloc {
        [self.playerItem removeObserver:self forKeyPath:@"status" context:nil];
        [self.playerItem removeObserver:self forKeyPath:@"loadedTimeRanges" context:nil];
    

    相关文章

      网友评论

          本文标题:KVO(观察者模式)

          本文链接:https://www.haomeiwen.com/subject/aebwsttx.html