【问题标题】:AVPlayer observeValueForKeyPathAVPlayer observeValueForKeyPath
【发布时间】:2012-08-01 20:44:21
【问题描述】:

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

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

作为一个特殊性,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 个警报,但没有人被触发,这意味着它没有进入该方法。所有这一切的目标是尝试实现一种让玩家在发生这种情况时重新启动的方法。

谢谢!

【问题讨论】:

    标签: ios5 audio-streaming avplayer avaudiosession addobserver


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      这是有效的代码。

      声明一个可观察的 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];
      }
      

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

      【讨论】:

        猜你喜欢
        • 2011-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-03
        相关资源
        最近更新 更多