检查indexPath上的单元格是否在屏幕UICollectionView上可见

时间:2016-07-09 12:38:46

标签: ios swift uicollectionview uicollectionviewcell nsindexpath

我有CollectionView向用户显示图片。我在后台下载这些,下载完成后,我调用以下函数来更新collectionViewCell并显示图像。

func handlePhotoDownloadCompletion(notification : NSNotification) {
    let userInfo:Dictionary<String,String!> = notification.userInfo as! Dictionary<String,String!>
    let id = userInfo["id"]
    let index = users_cities.indexOf({$0.id == id})
    if index != nil {
        let indexPath = NSIndexPath(forRow: index!, inSection: 0)
        let cell = followedCollectionView.cellForItemAtIndexPath(indexPath) as! FeaturedCitiesCollectionViewCell
        if (users_cities[index!].image != nil) {
            cell.backgroundImageView.image = users_cities[index!].image!
        }
    }
}

如果单元格当前在屏幕上可见,则效果很好,但如果不是,我会得到一个 以下行中出现fatal error: unexpectedly found nil while unwrapping an Optional value错误:

 let cell = followedCollectionView.cellForItemAtIndexPath(indexPath) as! FeaturedCitiesCollectionViewCell

现在,如果尚未看到collectionViewCell,则甚至不需要调用此函数,因为在这种情况下,无论如何都将在cellForItemAtIndexPath方法中设置图像。

因此我的问题是,如何更改此函数以检查我们正在处理的单元格当前是否可见。我知道collectionView.visibleCells()但是,我不知道如何在这里应用它。

7 个答案:

答案 0 :(得分:16)

获取当前可用的单元格

// get visible cells 
let visibleIndexPaths = followedCollectionView.indexPathsForVisibleItems()

然后检查indexPath是否包含在visibleIndexPaths中,然后再对单元格进行操作。

答案 1 :(得分:6)

嵌套的UICollectionViews根本不需要滚动,因此不会提供任何contentOffset,因此iOS会将所有单元格理解为始终可见。在这种情况下,可以将屏幕边界作为参考:

    let cellRect = cell.contentView.convert(cell.contentView.bounds, to: UIScreen.main.coordinateSpace)
    if UIScreen.main.bounds.intersects(cellRect) {
        print("cell is visible")
    }

答案 2 :(得分:2)

您可以通过以下方式获取当前索引

for col in ['U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD']:
    ws[col].protection = Protection(locked=False)

答案 3 :(得分:1)

您只需使用if collectionView.cellForItem(at: indexPath) == nil { }即可。只有在可见的情况下,collectionView才会返回一个单元格。

或者在你的情况下具体改变:

let cell = followedCollectionView.cellForItemAtIndexPath(indexPath) as! FeaturedCitiesCollectionViewCell

为:

if let cell = followedCollectionView.cellForItemAtIndexPath(indexPath) as? FeaturedCitiesCollectionViewCell { }

答案 4 :(得分:1)

我需要跟踪可见的单元格,以便您也可以执行类似的操作来更好地跟踪您的单元格。

private func configureVisibleIndexPath() {
        let visibleCells = collectionView.indexPathsForVisibleItems
        visibleCells.forEach { indexPath in
            if let cell = collectionView.cellForItem(at: indexPath), collectionView.bounds.contains(cell.frame) {
                print("visible row is \(indexPath.row)"
            }
        }
    }

当你的集合视图配置正确时调用这个函数,它还通过在 scrollView 委托中调用它来照顾滚动:

func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate {
        configureVisibleIndexPath()
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    configureVisibleIndexPath()
}

答案 5 :(得分:0)

是的,我尝试了很多方法,发现这是最好的。

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
   const currentIndex = (indexPath.row + 1) % (total cell number)
} 

答案 6 :(得分:-1)

您可以通过以下方式管理可见单元格。

https://github.com/NohEunTae/VisibilityTrackableCollectionView

只需设置要检测的边界:

collectionView.setBoundary(.init(view: someView, mode: .safeArea))