1

我有一个播放流内容的音频应用程序。问题是有时,当信号很弱时,它会停止播放。网络仍然可以访问,但缓冲区似乎已经空了。

我尝试实现一个观察者来监视玩家的状态变化,但它不起作用,该方法永远不会被调用。

作为一个特殊性,AVPlayer 实例位于 AppDelegate 中,因为我有多个视图,并且播放器必须继续播放显示的任何视图。所以这是一段示例代码:

- (void)viewDidLoad
    {
        [super viewDidLoad];
        isPlaying = false;
        playButton.enabled = NO;

        //Add en observer for reachability change
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(reachabilityChanged:) 
                                                     name:kReachabilityChangedNotification
                                                   object:nil];

        //Adding the observer for player's status change
        AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        [delegate.player addObserver:self forKeyPath:@"status" options:0 context:playerStatusContext];

        [self initPlayer];
    }


    //Event raised whenever the current status of the player change
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

        UIAlertView *alert = [UIAlertView alloc];
        NSString *chaineConcat = @"Entering observer method..."];
        [alert initWithTitle:@"Test" message:chaineConcat delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];   
        [alert show];

        if (context == playerStatusContext) {
            AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
            NSString *statusPlayer = nil; 
            if (object == delegate.player && [keyPath isEqualToString:@"status"]) {
                if (delegate.player.status == AVPlayerStatusReadyToPlay) {
                    statusPlayer = @"Everything's OK";
                } else if (delegate.player.status == AVPlayerStatusFailed) {
                    statusPlayer = @"Houston, we have a problem";
                }
            }
            [self syncUI];

            UIAlertView *alert = [UIAlertView alloc];
            NSString *chaineConcat = [NSString stringWithFormat:@"%@/%@/", @"Player status' is ", statusPlayer];
            [alert initWithTitle:@"Test" message:chaineConcat delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];   
            [alert show];

        }else {
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }

        return;
    }

- (void) initPlayer {

    // Load the array with the sample file
    NSString *urlAddress = @"http://MYSTREAMURL";

    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    //Create a URL object.
    delegate.urlStream = [NSURL URLWithString:urlAddress];

    //Reinit AVPlayer
    delegate.player = [AVPlayer playerWithURL:delegate.urlStream];

}

有谁知道为什么没有提出该事件?我在该方法中有 2 个警报,但没有人被触发,这意味着它没有进入该方法。所有这一切的目标是尝试实现一种让玩家在发生这种情况时重新启动的方法。

谢谢 !

4

2 回答 2

1

您正在尝试在创建要观察的对象之前添加观察者。您只是向nil对象发送消息。
打电话-initPlayer前打电话-addObserver:forKeyPath:options:context:

于 2013-03-14T22:06:33.993 回答
0

这是有效的代码。

声明一个可观察的 AVPlayer 对象:

@interface APLViewController ()
{
    AVPlayer *_player;
}

分配和初始化 AVPlayer:

- (void)viewDidLoad
{
[super viewDidLoad];

 _player = [[AVPlayer alloc] init];
}

添加观察者:

- (void)viewWillAppear:(BOOL)animated
{
    [self addObserver:self forKeyPath:@"player.currentItem.status" options:NSKeyValueObservingOptionNew context:AVPlayerItemStatusContext];
    [self addTimeObserverToPlayer];

    [super viewWillAppear:animated];
}

处理观察者:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == AVPlayerItemStatusContext) {
        AVPlayerStatus status = [change[NSKeyValueChangeNewKey] integerValue];
        switch (status) {
            case AVPlayerItemStatusUnknown:
                break;
            case AVPlayerItemStatusReadyToPlay:
                self.playerView.presentationRect = [[_player currentItem] presentationSize];
                break;
            case AVPlayerItemStatusFailed:
                [self stopLoadingAnimationAndHandleError:[[_player currentItem] error]];
                break;
        }
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

要删除观察者:

- (void)viewWillDisappear:(BOOL)animated
{
    [self removeObserver:self forKeyPath:@"player.currentItem.status" context:AVPlayerItemStatusContext];
    [self removeTimeObserverFromPlayer];

    [super viewWillDisappear:animated];
}

一定要把所有东西都放在我做过的地方,否则它可能不起作用。

于 2016-01-26T01:21:45.837 回答