我正在使用自定义创建的UITableViewCell实现一个丰富的UITableView,我以一种方式在屏幕上显示这些,但是一旦它们离开屏幕我想记下这一点,因为他们第二次出现我会喜欢他们以不同的方式展示。离开屏幕时想想自动“标记为已读”。
我一直在寻找某种方法来检测一个单元格何时离开屏幕(得到dealloc'ed或者出列或者等效),最好是在:UITableViewController类中快速记下[indexPath行],但是在:UITableViewCell同样出色。
我无法以任何标准的方式执行此操作...计算它出现的时间似乎是不可能的,因为我在表上执行了多次reloadData调用。
任何想法?这看起来有点棘手:)
答案 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 应该都匹配 cellForItem
和 didEndDisplaying
。