2012-08-01 34 views
1

我有一個播放流內容的音頻應用程序。問題有時候,當信號很弱時,它會停止播放。網絡仍然可以訪問,但緩衝區似乎已經空了。AVPlayer observeValueForKeyPath

我試圖實現一個觀察者來監視玩家的狀態變化,但它不工作,該方法永遠不會被調用。

作爲一個特殊性,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個警報,但沒有人被解僱,這意味着它沒有進入方法。所有這些的目標將是嘗試實現一種讓玩家在這種情況發生時重新啓動的方式。

謝謝!

回答

1

您正在嘗試在創建要觀察的對象之前添加觀察者。您只需發送消息給nil對象。
致電-initPlayer致電-addObserver:forKeyPath:options:context:

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

一定要放在哪裏我所做的一切,也可能無法正常工作。