简体   繁体   中英

Why the KVO on 'status' property of AVPlayer not get called on iOS 9 and 10

Like the title says, does anyone know the reason?
Note that it does not happen on iOS 11.

My debug environment:

  • Xcode 9.2
  • iOS 9, 10, 11

My code:

In my app, I am trying to play a streaming content by AVFoundation framework. Showing the video's length and current playing time is also a feature.
The loadVideo method is called in an IBAction due to a tapped button.
Also, no special code in observeValueForKeyPath method to receive the event of KVO.
The details is listed as following:

- (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"];
    }
}

Remote content doesn't work like local content.

In iOS 9, you should be using the AVPlayerItem as the locus of information about the arrival and playback of your AVAsset from across the network, keeping track of properties such as playbackLikelyToKeepUp and the accessLog , along with notifications such as AVPlayerItemPlaybackStalled .

In iOS 10 and later, you can use the AVPlayer, but the thing to watch is its timeControlStatus .

You should observe AVPlayerItem, not AVPlayer.

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

Apple's documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM