【问题标题】:Why the KVO on 'status' property of AVPlayer not get called on iOS 9 and 10为什么在 iOS 9 和 10 上不调用 AVPlayer 的“状态”属性的 KVO
【发布时间】:2025-11-26 10:45:02
【问题描述】:

如题,有人知道原因吗?
请注意,它不会在 iOS 11 上发生。

我的调试环境:

  • Xcode 9.2
  • iOS 9、10、11

我的代码:

在我的应用程序中,我正在尝试通过 AVFoundation 框架播放流媒体内容。显示视频的长度和当前播放时间也是一项功能。
loadVideo 方法在 IBAction 中由于点击按钮而被调用。
另外,observeValueForKeyPath 方法中没有特殊代码来接收 KVO 的事件。
详情如下:

- (void)loadVideo
{
    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:VIDEO_URL]];

    Float64 duration = CMTimeGetSeconds(item.asset.duration);
    [self updateTimeLabel:0.0 duration:duration];

    self.player = [[AVPlayer alloc] initWithPlayerItem:item];
    AVPlayerLayer *layer = (AVPlayerLayer *)self.playerView.layer;
    [layer setPlayer:self.player];
    [self.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

    __weak ViewController *weakSelf = self;
    self.token = [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, NSEC_PER_SEC)
                                                           queue:nil
                                                      usingBlock:^(CMTime time) {
                                                          Float64 currentTime = CMTimeGetSeconds(time);
                                                          [weakSelf updateTimeLabel:currentTime duration:duration];
                                                      }];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"status"]) {
    AVPlayer *player = (AVPlayer *)object;
    switch (player.status) {
        case AVPlayerStatusReadyToPlay:
        {
            NSLog(@"player's status changed to AVPlayerStatusReadyToPlay");
        }
            break;

        default:
            NSLog(@"player's status changed");
            break;
    }

    [player removeObserver:self forKeyPath:@"status"];
    }
}

【问题讨论】:

    标签: ios objective-c avplayer status key-value-observing


    【解决方案1】:

    远程内容不像本地内容那样工作。

    在 iOS 9 中,您应该使用 AVPlayerItem 作为有关通过网络到达和播放 AVAsset 的信息的位置,跟踪诸如 playbackLikelyToKeepUpaccessLog 之类的属性,以及诸如此类的通知作为AVPlayerItemPlaybackStalled

    在 iOS 10 及更高版本中,您可以使用 AVPlayer,但要注意的是它的 timeControlStatus

    【讨论】:

      【解决方案2】:

      你应该观察 AVPlayerItem,而不是 AVPlayer。

      [self.item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
      

      Apple's documentation

      【讨论】:

        最近更新 更多