AVVlayerItem.loadedTimeRanges上的KVO可能吗?

时间:2012-01-25 00:27:22

标签: ios avfoundation key-value-observing avplayer

Apples文档提到了它,但是如何为AVPlayerItem的loadedTimeRanges属性设置键值观察?该属性是一个不会改变的NSArray,所以你不能只使用playerItem addObserver:self forKeyPath:@"loadedTimeRanges ...

还是有其他方法可以在发生变化时收到通知或更新吗?

3 个答案:

答案 0 :(得分:7)

实际上,我正在使用KVO for loadedTimeRanges而没有任何麻烦。也许你只是没有设置正确的选项?以下是对Apple AVPlayerDemo中某些代码的轻微修改,它对我来说非常好。

//somewhere near the top of the file
NSString * const kLoadedTimeRangesKey   = @"loadedTimeRanges";
static void *AudioControllerBufferingObservationContext = &AudioControllerBufferingObservationContext;


- (void)someFunction
{  
    // ...

    //somewhere after somePlayerItem has been initialized
    [somePlayerItem addObserver:self
                       forKeyPath:kLoadedTimeRangesKey
                          options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                          context:AudioControllerBufferingObservationContext];

    // ...
}

- (void)observeValueForKeyPath:(NSString*) path 
                  ofObject:(id)object 
                    change:(NSDictionary*)change 
                   context:(void*)context
{
    if (context == AudioControllerBufferingObservationContext)
    {
        NSLog(@"Buffering status: %@", [object loadedTimeRanges]);
    }
}

答案 1 :(得分:2)

右。 loadedTimeRanges不会更改,但其中的对象会更改。您可以设置计时器每秒运行一次(左右)并检查loadedTimeRanges内的值。然后你会看到你正在寻找的变化。

dispatch_queue_t queue = dispatch_queue_create("playerQueue", NULL);

[player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1)
                                          queue:queue
                                     usingBlock:^(CMTime time) {  
                                         for (NSValue *time in player.currentItem.loadedTimeRanges) {
                                             CMTimeRange range;
                                             [time getValue:&range];
                                             NSLog(@"loadedTimeRanges: %f, %f", CMTimeGetSeconds(range.start), CMTimeGetSeconds(range.duration));
                                         }
                                     }];

答案 2 :(得分:0)

更新到Swift 4.0及更高版本:

loadedTimeRangesObserver = player.observe(\AVPlayer.currentItem?.loadedTimeRanges, options: [.new, .initial]) { [unowned self] (player, change) in
    DispatchQueue.main.async {    
        guard let ranges = change.newValue as? [CMTimeRange] else { return }
        // update UI
    }
}