Iphone 检测UITableViewCell何时离开屏幕

Iphone 检测UITableViewCell何时离开屏幕,iphone,uitableview,Iphone,Uitableview,我正在用自定义创建的UITableViewCell实现一个富UITableView,我以一种方式在屏幕上显示它们,但一旦它们离开屏幕,我想记下这一点,因为它们第二次出现时,我希望它们以不同的方式显示。离开屏幕时,考虑自动“标记为已读” 我一直在寻找某种方法来检测单元格何时离开屏幕(get's dealloc'ed或dequeued或等效),最好是在:UITableViewController类中快速记录[indexPath行],但在:UITableViewCell中也同样好 我还没能以任何标准的

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

我一直在寻找某种方法来检测单元格何时离开屏幕(get's dealloc'ed或dequeued或等效),最好是在:UITableViewController类中快速记录[indexPath行],但在:UITableViewCell中也同样好

我还没能以任何标准的方式做到这一点。。。计算它出现的次数似乎是不可能的,因为我在表上进行了多次重载数据调用


有人有什么想法吗?这似乎有点棘手:)

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

我认为您可以使用

- (NSArray *)visibleCells
方法来创建UITableView。这将返回所有可见单元格的数组。然后,您可以按照自己的方式标记任何“不可见”(即不在该数组中)的数据,这样当您滚动回该数据时,该数据已被更新


希望这会有所帮助

你确定屏幕外的手机正是你想要捕捉的吗?如果要将项目标记为已读,这似乎不是一种正确的方法。例如,我可能会快速浏览表格,如果您将所有内容都标记为已读,我会非常惊讶

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


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

安德烈·塔兰佐夫提到的UITableViewCell上的
prepareforeuse
方法看起来不错。在其中放入两个nslog,可以打印出单元格中任何变量的值。关于如何将其设置回表视图控制器的任何想法?

一旦
UITableViewCell
不可见,它将从
UITableView
中删除。您可以重写方法
-(void)removeFromSuperView
,并在该方法内执行某些操作。最后,别忘了调用
[super removeFromSuperView]
这是一个老问题,但如果有人正在查看,在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...
    }
}

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

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

当单元格从屏幕上滚下时,我需要从单元格中获取一些数据。我使用了,但是它没有说明如何获取数据

例如,我使用的cell类的名称是
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都应该匹配
cellForItem
didendisplaying

是的,这将是一个选项,我可以将该调用放在cellForRowAtIndexPath中。但是,我有可变高度的行,因此这不能保证屏幕外的单元格被标记为屏幕外:|我使用委托来完成这项工作。这是我正在寻找的解决方案,但对于iOS 5.0而言。有什么建议吗?不幸的是苹果没有提供任何建议。我所做的是使用scrollViewDidScroll并进行快速计算,以查看visibleCells数组自scrollview的上一个“帧”以来是否发生了更改,在这种情况下,我对现在缺少的单元格做了一些处理。希望有帮助!不幸的是,tableView.indexPathsForVisibleRows直到调用didEndDisplayingCell后才会更新,因此如果添加新的单元格,这些旧单元格将从显示中删除,但仍将位于tableView.indexPathsForVisibleRows中。(至少对于iOS 7来说是这样)。@Olof\t情况似乎确实如此,所以我只是查看了iOS 7应用程序的tableView.indexPathsForVisibleRows。我还在相应的willDisplayCell:方法中添加了一些代码来处理一些角落的情况。我用它来停止单元格内的视频播放,因为只要视频继续播放,就不会调用DiEndDisplayingCell。这似乎不是一个可靠的解决方案。我刚刚在iOS 6.0模拟器上测试过,这些单元格似乎被设置为隐藏,而不是被移除。奇怪的是,
setHidden:YES
在我的实现中也没有被调用!显然,在tableView实现中,ivar是直接设置的,跳过了属性设置器方法。子类化UITableViewCell后,不会调用removeFromSuperView方法