【问题标题】:Is KVO on AVPlayerItem.loadedTimeRanges possible?AVPlayerItem.loadedTimeRanges 上的 KVO 可能吗?
【发布时间】:2012-01-25 00:27:21
【问题描述】:

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

或者是否有其他方法可以在这种情况发生变化时获取通知或更新?

【问题讨论】:

    标签: ios avfoundation key-value-observing avplayer


    【解决方案1】:

    实际上,我使用 KVO 进行加载时间范围没有任何问题。也许您只是没有设置正确的选项?以下是对 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]);
        }
    }
    

    【讨论】:

    • 是的,这是选项,我将其设置为 0。谢谢!
    • 我逐字尝试了这个解决方案。不幸的是,我收到了一个对 loadedTimeRanges 的初始 KVO 调用,它返回一个空的 NSArray,然后什么也没有。
    • 事实证明,我可以为loadedTimeRanges 工作的唯一选择是NSKeyValueObservingOptionInitial。对我来说,解决方法是使用 Timer(实际上是 CADisplayLink)在 UIProgressView 出现在屏幕上时检查 loadedTimeRanges 属性。这可行,但对我来说确实很笨拙。我宁愿 KVO 任何新的价值观。
    • 我发现和 Chris L 一样。令人沮丧的是,它第一次工作,但在我更改播放器项目后,我得到每个回调 butloadedTimeRanges
    • @RobertDiamond 你找到解决办法了吗?
    【解决方案2】:

    没错。 loadTimeRanges 不会改变,但它里面的对象会改变。您可以设置一个计时器以每秒(或左右)运行一次并检查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));
                                             }
                                         }];
    

    【讨论】:

    • 这不会在 AVPlayer 暂停时触发。
    • @Andy 不确定你的意思。这对我来说非常有效。暂停时,loadedTimeRanges 将停止记录,但一旦您恢复,它们将继续记录,很明显,值在暂停时仍在更新。
    【解决方案3】:

    更新到 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
        }
    }     
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 2012-08-25
      • 1970-01-01
      相关资源
      最近更新 更多