wkx
wkx

Reputation: 441

After AVPlayer's first failure, I can never receive KVO callback any more

Just as what I explain above, If I start the app and first turn off the wifi and then try to play a music with AVPlayer, I will receive a AVPlayerItemStatusFailed, but after that, I can no longer receive any KVO callback even if I turn on the wifi again.

On the other situation, if I run the app and first to turn on wifi and play, I can receive AVPlayerItemStatusReadyToPlay and after that, I can continue to receive KVO callback even if I turn wifi off...

So how to fix the first situation??

@interface ViewController ()

@property (strong, nonatomic) AVPlayer *player;
@property (assign, nonatomic) NSInteger index;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (IBAction)buttonPressed:(UIButton *)sender {
    [self.player.currentItem removeObserver:self forKeyPath:@"status"];
    NSLog(@"removed %@", self.player.currentItem);

    AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:self.urls[self.index]]];

    [item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    NSLog(@"added %@", item);

    [self.player replaceCurrentItemWithPlayerItem:item];

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"]) {
        if ([object isMemberOfClass:[AVPlayerItem class]]) {
            AVPlayerItem *playerItem = (AVPlayerItem *)object;
            switch (playerItem.status) {
                case AVPlayerItemStatusFailed:
                    NSLog(@"failed");
                    break;
                case AVPlayerItemStatusReadyToPlay:
                    NSLog(@"ready");
                    break;
                case AVPlayerItemStatusUnknown:
                    NSLog(@"unknown");
                    break;
            }
        }
    }
}

- (AVPlayer *)player {
    if (!_player) {
        _player = [[AVPlayer alloc] init];
    }
    return _player;
}

- (NSArray *)urls {
    return @[@"https://of92d29bn.qnssl.com/record1.m4a", @"https://of92d29bn.qnssl.com/record2.m4a"];
}

- (NSInteger)index {
    if (_index == 0) {
        _index = 1;
    } else {
        _index = 0;
    }
    return _index;
}

This is all my code.

Upvotes: 1

Views: 403

Answers (1)

hybridcattt
hybridcattt

Reputation: 3041

I had the same issue and found a solution:

Reset current item to nil before using the new one:

[self.player replaceCurrentItemWithPlayerItem:nil];
[self.player replaceCurrentItemWithPlayerItem:item];

This doesn't make much sense, and there's probably a bug in AVPlayer's implementation somewhere. But this worked for me.

Upvotes: 1

Related Questions