应用场景

在 UITableViewCell 中嵌入一个播放器
当某一个 Cell 被移出屏幕的时候,对改 Cell 进行处理,包括暂停或停掉播放器,或者其他的操作.

基本思路

关于判断 UITableViewCell 是否移出屏幕,可以先了解怎么判断 Cell 在屏幕中
1. UITableView 有两个关于 Cell可用的属性

@property (nonatomic, readonly) NSArray<__kindof UITableViewCell *> *visibleCells;
  @property (nonatomic, readonly, nullable) NSArray<NSIndexPath *> *indexPathsForVisibleRows;

使用两个属性可以获取到 UITableView 的可视范围内的相关属性,一 个是 Cell 的数组还有一个是 NSIndexPath 数组.不过在实际操作中发现使用这两个属性来做为判断依据不是非常准确,所以放弃使用.
2. 第二个就是从 frame 相关信息入手,对于一个 Cell 来说,大概的关系是UIView(即 VC 视图) -> UITableView ->UITableViewCell, 就是说先将 Cell 在 UITableView 中的位置找到,然后通过转换函数转换成在 VC 视图的位置,这种方法是比较准确,暴力的方法,所以使用该方法来处理我们需要的业务逻辑.即

CGRect rectInTableView = [_tableView rectForRowAtIndexPath: self.operatedCellIndexPath];

CGRect rectInSuperview = [_tableView convertRect:rectInTableView toView:[_tableView superview]];

关于在 UICollectionView中的实现方式类似,不过由于 UICollectionView 中并没有 rectForRowAtIndexPath: 这种方法,所以使用

CGRect cellRect = [_collectionView convertRect:self.currentPlayingCell.frame toView:_collectionView];

CGRect rectInSuperview = [_collectionView convertRect:cellRect toView:self.view];

这种方式,思路是一致的.

具体实现

到这里,我们的需求基本上已经完成了,剩下需要做的就是记录下我们需要操作的 Cell, 因为我们判断 Cell 移出屏幕,肯定是对已经操作过的 Cell 进行下一步处理,比如视频的暂停或者停止播放等等.这样可以写个 Block,在加载 Cell 的时候记录下我们操作的 Cell,本文就是在播放视频的时候,调用 block 记录下当前的 Cell,并且停止正在播放的 Cell 中的 VideoPlayer.

WEAKSELF
    cell.startPlayVideoAction = ^(){
        STRONGSELF
        // 这个地方可以对上一次记录的 Cell 和 IndexPath 进行处理,比如我就可以把正在播放的视频停掉,类似这样 

        // 记录 当前被点击 cell 的位置和 indexPath
        strongSelf.operatedCellIndexPath = indexPath;
        strongSelf.currentPlayingCell = [strongSelf.tableView cellForRowAtIndexPath: indexPath];
    };

最后一步就是在 UITableView 或者 UICollectionView 滑动的时候进行监听了

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
  // 这里我记录了 Cell 的 IndexPath 和 Cell
    if ( self.operatedCellIndexPath != nil ) {
        CGRect rectInTableView = [self.tableView rectForRowAtIndexPath: self.operatedCellIndexPath];
        CGRect rectInSuperview = [self.tableView convertRect:rectInTableView toView:[self.tableView superview]];
        if ( rectInSuperview.origin.y > SCREEN_HEIGHT || rectInSuperview.origin.y + rectInSuperview.size.height < 0 ) {
           // 对已经移出屏幕的 Cell 做相应的处理
        }
    }
}

本文主要以 UITableView 为例子,进行总结,不过 UICollectionView 大概的思路是一直的,不过是在获取 Cell 的 frame 的时候的方式不一样罢了.