📅  最后修改于: 2023-12-03 15:05:26.087000             🧑  作者: Mango
在开发 iOS 应用时,经常需要使用 UICollectionView 来展示数据列表,在 UICollectionView 中,每个单元格都是一个 UICollectionViewCell 。有时,我们需要在屏幕上显示很多个单元格,但有些单元格可能因为滑动超过了屏幕范围而不再需要显示,此时我们需要对这些不再需要显示的单元格进行清理操作。
所以,我们需要知道何时离开屏幕的单元格。在 Swift 中,可以通过 UICollectionViewDelegate 或者 UICollectionViewFlowLayoutDelegate 来实现这一功能。
UICollectionViewDelegate 协议中包含 scrollViewDidEndDecelerating、scrollViewDidEndDragging、scrollViewDidEndScrollingAnimation 三个方法,可以确定 UICollectionViewCell 何时离开屏幕。
以 scrollViewDidEndDecelerating 方法为例,代码如下:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
guard let collectionView = scrollView as? UICollectionView else {
return
}
for cell in collectionView.visibleCells {
if !collectionView.bounds.intersects(cell.frame) {
// cell 离开了屏幕
// 在这里可以进行清理操作
}
}
}
在 scrollViewDidEndDecelerating 方法中,首先通过 guard let 判断 scrollView 是不是 UICollectionView,然后遍历所有正在展示的 UICollectionViewCell,通过判断 cell.frame 是否与 collectionView.bounds 相交,来确定 cell 是否离开屏幕。
UICollectionViewFlowLayoutDelegate 协议中包含 layoutAttributesForElements(in rect: CGRect) 方法,该方法返回在 rect 区域内需要展示的 UICollectionViewLayoutAttributes 数组。我们可以通过该方法精确定位哪些 UICollectionViewCell 离开了屏幕,从而进行清理操作。
以 layoutAttributesForElements(in rect: CGRect) 方法为例,代码如下:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
attributesForElementsIn rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect)
for attribute in attributes ?? [] {
if !collectionView.bounds.intersects(attribute.frame) {
// attribute 所表示的单元格离开了屏幕
// 在这里可以进行清理操作
}
}
return attributes
}
在 collectionView(_:layout:attributesForElementsIn:) 方法中,首先调用了父类的方法,获取 rect 区域内正在展示的 UICollectionViewLayoutAttributes 数组,然后遍历每一个获取到的 UICollectionViewLayoutAttributes,判断其 frame 是否与 collectionView.bounds 相交,来确定哪些 UICollectionViewCell 离开了屏幕。
以上就是两种解决方案,可以根据实际需要来选择使用哪种方案来实现清理屏幕外的 UICollectionView。