AVPlayerItem addobserver issue in iOS8

匿名 (未验证) 提交于 2019-12-03 08:59:04

问题:

Hi I am playing video on my UITableViewCells using AVPlayer, It was working fine on iOS 7, but in iOS8 it crashing with following error.

       'An instance 0x7c01b000 of class AVPlayerItem was deallocated while key value observers were still registered with it. 

Here is my code

      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath          {            .........           .........          if(cell.videoPlayer!= nil && cell.videoPlayer.currentItem != nil)             {               [cell.videoItem removeObserver:self forKeyPath:@"playbackBufferEmpty" context:nil];                [cell.videoItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp" context:nil];                 }      cell.videoPlayer = [AVPlayer playerWithPlayerItem:cell.videoItem];      cell.avLayer = [AVPlayerLayer playerLayerWithPlayer:cell.videoPlayer];      cell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone;       [cell.videoItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionInitial context:nil];      [cell.videoItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionInitial context:nil];       [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil];       [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];      cell.avLayer.frame = CGRectMake(5, 9, 310, 310);    [cell.contentView.layer addSublayer:  cell.avLayer];    [ cell.videoPlayer play];    [cell.contentView addSubview:cell.videoActivity];        return cell;     }       -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object                change:(NSDictionary *)change context:(void *)context {           NSArray* cells = homeTabl.visibleCells;        for (HomeCell* cell in cells) {          if (object == cell.videoItem && [keyPath isEqualToString:@"playbackBufferEmpty"])                 {     if (cell.videoItem.playbackBufferEmpty) {          NSLog(@"buffering");         cell.videoActivity.hidden = NO;           }     }         else if (object == cell.videoItem && [keyPath isEqualToString:@"playbackLikelyToKeepUp"])     {          if (cell.videoItem.playbackLikelyToKeepUp)         {           cell.videoActivity.hidden = YES;         [cell.videoPlayer play];             }         }        }      }    -(void)scrollViewDidScroll:(UIScrollView *)aScrollView {      NSArray* cells = homeTabl.visibleCells;      for (HomeCell* cell in cells) {      [cell.videoPlayer pause];     [cell.avLayer removeFromSuperlayer];     cell.videoPlayer = nil;     cell.videoItem = nil;      } 

What could be the reason ? I have gone through this SO question, but I could not implement this in my codes. Please help me to fix this.

回答1:

Removing observers is one of the flakiest areas in iOS in my experience. You need to balance calls for AddObserver with a RemoveObserver very carefully. I have found a failsafe way to do this is to put any AddObserver calls into an object's Init method and then balance these with RemoveObserver calls in its Dealloc method. In your case this would be in your 'videoItem' subclass. (this code is not checked)

- (id) initWithOwner:(id)owner {     self = [super init];     if( self ) {         _owner = owner;         [self addObserver:_owner forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionInitial context:nil];     }     return self; }  - (void) dealloc {     [self removeObserver:_owner forKeyPath:@"playbackBufferEmpty" context:nil]; } 

I'm not sure where videoItem is declared but basically you create a new class called VideoItem and in it create a new initialiser called initWithOwner:. In your cellForRowAtIndexPath: method when you create your new cell you also create an instance of VideoItem and pass in self as the owner

self.videoItem = [[VideoItem alloc] initWithOwner:self]; 

Without more of your code I can't really specify this in more detail. You might also think of formatting your code first in xcode then cutting and pasting it into SO to keep it tidier.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!