Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer was deallocated while key value observers were still registered with it

I am creating a simple media player app. My App is crashed when first link is played and I clicked second link in uitableview.

- (void)viewDidLoad {         [super viewDidLoad];         arrURL = [NSArray arrayWithObjects: @"http://yp.shoutcast.com/sbin/tunein-station.pls?id=148820", @"http://www.kcrw.com/pls/kcrwmusic.pls",@"http://yp.shoutcast.com/sbin/tunein-station.pls?id=175821",@"http://yp.shoutcast.com/sbin/tunein-station.pls?id=148820",@"http://yp.shoutcast.com/sbin/tunein-station.pls?id=70931",nil];         url = [[NSURL alloc] init];         }      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {          return [arrURL count];     }  - (UITableViewCell *)tableView:(UITableView *)tableView          cellForRowAtIndexPath:(NSIndexPath *)indexPath {     static NSString *MyIdentifier = @"MyIdentifier";     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];     if (cell == nil)     {         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ;     }      cell.textLabel.text = [arrURL objectAtIndex:indexPath.row];     return cell; }  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {     selectedSongIndex = indexPath.row;     url = [[NSURL alloc] initWithString:[arrURL objectAtIndex:indexPath.row]];     [self setupAVPlayerForURL:url];     [player play];      //[tableView deselectRowAtIndexPath:indexPath animated:YES]; } - (IBAction)btnPlay_Click:(id)sender {      [player play];     AVPlayerItem *item = player.currentItem;     [item addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionInitial| NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld| NSKeyValueObservingOptionPrior context:nil]; } - (IBAction)btnPause_Click:(id)sender {      [player pause]; }  - (IBAction)btnStop_Click:(id)sender {      [player pause]; } -(void) setupAVPlayerForURL: (NSURL*) url1 {     AVAsset *asset = [AVURLAsset URLAssetWithURL:url1 options:nil];     AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset];      player = [AVPlayer playerWithPlayerItem:anItem]; **//Application Crashed**     [player addObserver:self forKeyPath:@"status" options:0 context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {     if([keyPath isEqualToString:@"timedMetadata"])     {         AVPlayerItem *item = (AVPlayerItem *)object;         NSLog(@"Item.timedMetadata: %@",item.timedMetadata);         NSLog(@"-- META DATA ---");         //        AVPlayerItem *pItem = (AVPlayerItem *)object;         for (AVMetadataItem *metaItem in item.timedMetadata) {             NSLog(@"meta data = %@",[metaItem commonKey]);             NSString *key = [metaItem commonKey]; //key = publisher , key = title             NSString *value = [metaItem stringValue];             NSLog(@"key = %@, value = %@", key, value);             if([[metaItem commonKey] isEqualToString:@"title"])             {                 self.lblTitle.text = [metaItem stringValue];             }         }     }     if (object == player && [keyPath isEqualToString:@"status"]) {         if (player.status == AVPlayerStatusFailed) {             NSLog(@"AVPlayer Failed");         } else if (player.status == AVPlayerStatusReadyToPlay) {             NSLog(@"AVPlayer Ready to Play");         } else if (player.status == AVPlayerItemStatusUnknown) {             NSLog(@"AVPlayer Unknown");         }     } } 

I got this message when App crashed.

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x165297c0 of class AVPlayer was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x1661d5d0> )'

Application crashed only in IOS 8 in IOS 7 works fine. What I am doing wrong??

like image 215
Mihir Oza Avatar asked Oct 08 '14 12:10

Mihir Oza


1 Answers

I had a similar problem. It worked fine in iOS 7, and now it crashes in iOS 8.

The solution was to remove the observer, before releasing the object.

When you replace or allocate a new object for a member, you're releasing the old object, so you need to remove the observer first :

-(void) setupAVPlayerForURL: (NSURL*) url1 {     AVAsset *asset = [AVURLAsset URLAssetWithURL:url1 options:nil];     AVPlayerItem *anItem = [AVPlayerItem playerItemWithAsset:asset];     if (player != nil)         [player removeObserver:self forKeyPath:@"status"];     player = [AVPlayer playerWithPlayerItem:anItem];      [player addObserver:self forKeyPath:@"status" options:0 context:nil]; } 

And similarly in btnPlayClick ( in case it is pressed without btnStop_Click being pressed) :

- (IBAction)btnPlay_Click:(id)sender {      if (player != nil && [player currentItem] != nil)          [[player currentItem] removeObserver:self forKeyPath:@"timedMetadata"];     AVPlayerItem *item = player.currentItem;     [item addObserver:self forKeyPath:@"timedMetadata" options:NSKeyValueObservingOptionInitial|     NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld| NSKeyValueObservingOptionPrior context:nil];     [player play]; } 
like image 199
Ralph Avatar answered Sep 19 '22 13:09

Ralph