UICollectionViewCells中的AVPlayers最终在滚动后崩溃应用程序

时间:2015-04-09 03:35:32

标签: ios objective-c avfoundation grand-central-dispatch avplayer

我正在尝试创建一个类似于Vine的应用程序,它只是一个单元格的源,当您滚动并停止在单元格上时,视频会自动播放。

每个UICollectionViewCell都有自己的AVPlayer

现在我的当前设置在大多数情况下工作正常,但在滚动一段时间后,应用程序最终崩溃,我的分析SDK显示崩溃是由以下错误引起的:

An AVPlayerItem cannot be associated with more than one instance of AVPlayer

在控制台收到内存警告后,应用程序有时会崩溃。

我觉得这与我如何为每个AVPlayers设置UICollectionViewCell以及如何重复使用这些单元格有关,但我并不完全确定。

以下是我目前在View Controller中处理设置单元格及其AVPlayers的代码:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

   MyCollectionViewCellSubclass *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
   [cell load:self.objectsFromServer[indexPath.row] withBannerColor:self.bannerColors[indexPath.row % self.bannerColors.count]];

   QBCOCustomObject *objectFromServer = self.objectsFromServer[indexPath.row];

   NSURL *videoURL = [NSURL URLWithString:objectFromServer.fields[@"Video_URL"]];

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

    dispatch_async(queue, ^{
        cell.playerItem = [AVPlayerItem playerItemWithURL:videoURL];

        dispatch_sync(dispatch_get_main_queue(), ^{

            cell.player = [AVPlayer playerWithPlayerItem:cell.playerItem];
            cell.playerLayer = [AVPlayerLayer playerLayerWithPlayer:cell.player];
            cell.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

            cell.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
            cell.playerLayer.frame = CGRectMake(0, 0, 320, 186.5);
            [cell.banner.layer addSublayer:cell.playerLayer];

        });
    });

}
  return cell;
}

我使用scrollViewDidScroll:来处理单元格的播放/暂停。我检查以确保当前可见的单元格不是lastPlayingCell /播放视频的单元格,如果不是,则暂停lastPlayingCell并播放现在可见单元格的视频。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{ 

// Play/Pause Video
CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
NSLog(@"%@",visibleIndexPath);

MyCollectionViewCellSubclass *cell = (MyCollectionViewCellSubclass *)[self.collectionView cellForItemAtIndexPath:visibleIndexPath];

if (cell != self.lastPlayingCell) {

    [self.lastPlayingCell pauseVideo];
    self.lastPlayingCell = cell;
    [cell playVideo];
  }
}

1 个答案:

答案 0 :(得分:4)

这一行[cell.banner.layer addSublayer:cell.playerLayer];每当重复使用一个单元格时,都会添加一个新的playerLayer。在添加之前,您需要检查单元格是否已有播放器。如果已有,请使用replaceCurrentItemWithPlayerItem:为玩家提供新的AVPlayerItem