检测UITableViewCell何时离开屏幕

时间:2009-05-08 17:54:59

标签: iphone uitableview

我正在使用自定义创建的UITableViewCell实现一个丰富的UITableView,我以一种方式在屏幕上显示这些,但是一旦它们离开屏幕我想记下这一点,因为他们第二次出现我会喜欢他们以不同的方式展示。离开屏幕时想想自动“标记为已读”。

我一直在寻找某种方法来检测一个单元格何时离开屏幕(得到dealloc'ed或者出列或者等效),最好是在:UITableViewController类中快速记下[indexPath行],但是在:UITableViewCell同样出色。

我无法以任何标准的方式执行此操作...计算它出现的时间似乎是不可能的,因为我在表上执行了多次reloadData调用。

任何想法?这看起来有点棘手:)

8 个答案:

答案 0 :(得分:64)

这是一个老问题,但是如果有人在寻找,在iOS6中,引入了一个新的UITableViewDelegate函数:

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

在删除单元格时,它会很好地告诉您,但是,它非常彻底,因此如果您执行了重新加载单元格,即使被替换的旧单元格也会触发此委托功能。在我的实现中,我只是检查传递的indexPath是否仍在数组tableView.indexPathsForVisibleRows中。类似的东西:

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([tableView.indexPathsForVisibleRows indexOfObject:indexPath] == NSNotFound)
    {
        // This indeed is an indexPath no longer visible
        // Do something to this non-visible cell...
    }
}

答案 1 :(得分:6)

我认为你可以使用

- (NSArray *)visibleCells

UITableView的方法。这将返回所有可见单元格的数组。然后,您可以按照您想要的方式标记“不可见”(即不在此数组中)的任何数据,这样当您向后滚动它时,它已被更新。

希望有所帮助

答案 2 :(得分:6)

一旦UITableViewCell不可见,它将从UITableView中删除。您可以覆盖方法-(void)removeFromSuperView,并在方法中执行某些操作。最后,不要忘记致电[super removeFromSuperView]

答案 3 :(得分:2)

Andrey Tarantsov提到的UITableViewCell上的prepareForReuse方法看起来不错。在其中放置几个​​NSLog允许您打印出单元格的任何变量的值。有关如何将其设置回表视图控制器的任何想法?

答案 4 :(得分:1)

你确定一个离屏的细胞正是你要捕获的吗?如果要将项目标记为已读,则这似乎不是一种正确的方法。例如,我可能会快速滚动表格,如果您将所有内容标记为已阅读,我会非常惊讶。

对于技术部分,只需保留屏幕上的单元格列表(cellForRowAtIndexPath应将单元格添加到该列表),并在scrollViewDidScroll委托方法中检查是否有任何单元格不再可见。

另一个可能的想法:我记得单元格上有prepareForReuse方法。但不确定它何时被调用。

答案 5 :(得分:1)

我知道这是一个非常老的问题,但是如果有人在寻找 Swift 5 的答案,

func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    <#code#>
}

答案 6 :(得分:0)

我想我会尝试定期检查UITableView的indexPathsForVisibleRows属性。从最大的索引路径,您可以推断出所有先前的行都已滚动过去。

答案 7 :(得分:0)

当单元格滚动离开屏幕时,我需要从单元格中获取一些数据。我使用了 @Mr.T's answer 但它没有说明如何获取数据。

例如,我使用的单元类的名称是 MyCell,它有一个名为 MyModel 的数据模型,其属性为 postId。我最初在 cellForItem 中设置了该信息:

var datasource = [MyModel]()

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MyCell

    cell.myModel = datasource[indexPath.item] // an individual instance of MyModel from the array

    print("cellForItem - indexPath.item: ", indexPath.item) // if the was the very first cell coming on it would print 0
    print("postId: ", cell.myModel.postId) // maybe the postId is qwerty

    return
}

要在单元格滚出屏幕时从单元格中获取一些数据:

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

    guard let myCell = cell as? MyCell else { return } // You must cast the cell from the method param to your cell type which for me is MyCell

    print("didEndDisplayingCell - indexPath.item: ", indexPath.item) // if this was the very first cell scrolling off it should print 0
    print("postId: ", myCell.myModel.postId) // the postId should be qwerty
}

最好的测试方法是向 collectionView 添加少量单元格,例如前 2 个单元格,然后是 3 个单元格,然后是 4 个单元格。然后只需滚动第一个单元格,看看打印出来的内容。对每个单元格执行此操作。 indexPath.item 和 postId 应该都匹配 cellForItemdidEndDisplaying