繁体   English   中英

iOS8中的AVPlayerItem addobserver问题

[英]AVPlayerItem addobserver issue in iOS8

嗨,我正在使用AVPlayer在我的UITableViewCells上播放视频,它在iOS 7上工作正常,但在iOS8中崩溃时出现以下错误。

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

这是我的代码

      - (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;


   }

可能是什么原因 ? 我已经解决了这个问题,但我无法在我的代码中实现这一点。 请帮我解决这个问题。

根据我的经验,删除观察者是iOS中最脆弱的领域之一。 您需要非常小心地平衡AddObserver与RemoveObserver的调用。 我发现一种故障安全的方法是将任何AddObserver调用放入对象的Init方法中,然后在Dealloc方法中使用RemoveObserver调用来平衡它们。 在你的情况下,这将在你的'videoItem'子类中。 (未检查此代码)

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

我不确定在哪里声明了videoItem,但基本上你创建了一个名为VideoItem的新类,并在其中创建一个名为initWithOwner:的新初始化器。 在您的cellForRowAtIndexPath:方法中,当您创建新单元格时,您还可以创建一个VideoItem实例并作为所有者传入self

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

没有更多的代码,我无法更详细地指定它。 您可能还会考虑先在xcode中格式化代码,然后将其剪切并粘贴到SO中以保持其更整洁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM