2017-03-07 42 views
0

我收到以下错误,但奇怪的是,它只有当我使用分页,装载第二组的职位做滚动我的tableview发生,比我试图搬出新的视图控制器, 如果我只加载职位的第一页,并移动到另一个视图控制器,没有崩溃:类AVPlayerItem被释放,而键值观察员仍录

Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'An instance 0x170212330 of class AVPlayerItem was deallocated while key 
value observers were still registered with it. 
Current observation info: <NSKeyValueObservationInfo 0x174820360> (
<NSKeyValueObservance 0x174244290: Observer: 0x101c76c00, Key path: 
playbackBufferEmpty, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, 
Property: 0x174243ea0> 
<NSKeyValueObservance 0x1754583c0: Observer: 0x101c76c00, Key path: 
playbackLikelyToKeepUp, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, 
Property: 0x174243f60> 

我有一个球员在我的手机,这里是我的代码视图控制器:

- (UITableViewCell *)tableView:(UITableView *)tableViewSelected cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSString *identifier = @"postCell"; 
    PostCell* updateCell = [tableViewSelected dequeueReusableCellWithIdentifier:identifier]; 

     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 

     dispatch_async(queue, ^{ 

      dispatch_sync(dispatch_get_main_queue(), ^{ 
       NSLog(@"ADD VIDEO PLAYER and PLAY VIDEO"); 



       NSString* videoString = [NSString stringWithFormat:@"%@%@%@",UrlBase,PostVideos,post.video]; 
       NSString* expandedPath = [videoString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
       NSURL *videoURL = [NSURL URLWithString:expandedPath]; 
       NSLog(@"URL : %@",videoURL); 


       updateCell.videoItem = [AVPlayerItem playerItemWithURL:videoURL]; 

       [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
       [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

       updateCell.videoPlayer = [AVPlayer playerWithPlayerItem:updateCell.videoItem]; 
       updateCell.avLayer = [AVPlayerLayer playerLayerWithPlayer:updateCell.videoPlayer]; 
       updateCell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

       [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
       [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:[updateCell.videoPlayer currentItem]]; 


       updateCell.avLayer.frame = updateCell.picture.bounds; 
       [updateCell.videoView.layer addSublayer:updateCell.avLayer]; 

       [updateCell.avLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
       if(indexPath.row==0){ 
        [updateCell.videoPlayer play]; 
       } 
      }); 
     }); 
     return updateCell; 

} 

我可以添加第二个页面看到的唯一区别是:

在做常规表视图负荷我做的:

[_tableView reloadData]; 

当加载在同一个表视图中的第二页我做的:

[_tableView beginUpdates]; 
[_tableView insertRowsAtIndexPaths:[[GlobalSingleton sharedInstance] indexPathsToInsert] withRowAnimation:UITableViewRowAnimationTop]; 
[_tableView endUpdates]; 

比对我的手机我做的:

- (void)prepareForReuse{ 
    [self removePlayer]; 

} 

- (void) dealloc { 
[self removePlayer]; 
} 

-(void)removePlayer{ 
    @try{ 

    [self.videoItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; 
    [self.videoItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; 




    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

     NSLog(@"remove Observer!"); 
    // [avLayer.player pause]; 
    } 
    @catch (NSException * e) { 
     NSLog(@"Exception: %@", e); 
    } 
    @finally { 
     NSLog(@"finally"); 
     [self.avLayer removeFromSuperlayer]; 
     self.playIV.hidden = YES; 
     self.videoActivity.hidden = YES; 
     self.videoView.hidden = YES; 
     self.videoItem = nil; 
     self.avLayer = nil; 
     self.videoPlayer = nil; 
    } 

} 

难道insertRowsAtI ndexPaths是引起细胞永远dealloc的?我怎么也找不到它可能有注册的观察员。

+0

我的解决办法是删除2第一观察者: [updateCell.videoItem addObserver:updateCell forKeyPath:@“playbackBufferEmpty”options:NSKeyValueObservingOptionNew context:nil]; [updateCell.videoItem addObserver:updateCell forKeyPath:@“playbackLikelyToKeepUp”options:NSKeyValueObservingOptionNew context:nil]; –

+0

我也想通了prepareForReuse似乎不能很好地工作与insertRowsAtIndexPaths,但如果我创建新videoItem之前卸下的cellForRowAtIndexPath观察员,它也适用。 –

回答

0

不知怎的,使用insertRowsAtIndexPaths时,该prepareForReuse没有被调用,所以我决定它加入了新的videoItem到小区之前注销上的cellForRowAtIndexPath观察员:

- (UITableViewCell *)tableView:(UITableView *)tableViewSelected cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
NSString *identifier = @"postCell"; 
PostCell* updateCell = [tableViewSelected dequeueReusableCellWithIdentifier:identifier]; 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 

    dispatch_async(queue, ^{ 

     dispatch_sync(dispatch_get_main_queue(), ^{ 
      NSString* videoString = [NSString stringWithFormat:@"%@%@%@",UrlBase,PostVideos,post.video]; 
      NSString* expandedPath = [videoString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
      NSURL *videoURL = [NSURL URLWithString:expandedPath]; 

      /** SOLUTION STARTS HERE **/ 
      @try{ 
        [self.videoItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; 
        [self.videoItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; 
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:nil]; 
        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 

      } 
      @catch (NSException * e) { 
       NSLog(@"Exception: %@", e); 
      } 
      @finally { 
       NSLog(@"finally"); 
      } 
      /** SOLUTION ENDS HERE **/ 

      updateCell.videoItem = [AVPlayerItem playerItemWithURL:videoURL]; 
      [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 
      [updateCell.videoItem addObserver:updateCell forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 

      updateCell.videoPlayer = [AVPlayer playerWithPlayerItem:updateCell.videoItem]; 
      updateCell.avLayer = [AVPlayerLayer playerLayerWithPlayer:updateCell.videoPlayer]; 
      updateCell.videoPlayer.actionAtItemEnd = AVPlayerActionAtItemEndNone; 

      [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidBufferPlaying:) name:AVPlayerItemPlaybackStalledNotification object:nil]; 
      [[NSNotificationCenter defaultCenter] addObserver:updateCell selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:[updateCell.videoPlayer currentItem]]; 


      updateCell.avLayer.frame = updateCell.picture.bounds; 
      [updateCell.videoView.layer addSublayer:updateCell.avLayer]; 

      [updateCell.avLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
      if(indexPath.row==0){ 
       [updateCell.videoPlayer play]; 
      } 
     }); 
    }); 
    return updateCell; 

}