2012-08-01 3 views
1

У меня есть аудио-приложение, которое воспроизводит контент потока. Иногда возникает проблема, когда сигнал слабый, он перестает играть. Сеть по-прежнему доступна, но буфер, похоже, запущен пустым.AVPlayer observValueForKeyPath

Я попытался реализовать наблюдателя, чтобы контролировать изменение статуса игрока, но он не работает, метод просто не вызван.

Как особенность, экземпляр 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]; 
} 

Не забудьте положить все, где я сделал, или это может не сработать.

Смежные вопросы