结束显示时如何重新加载 collectionView 单元格?

How to reload collectionView cell when it did end displaying?

我创建了一个用户入职培训作为 Collection View,有 5 个单元格(页面)。

我有 2 种类型的集合视图 ItemswelcomeCell 它始终是入职培训中的第一个单元格(indexPath.item == 0)和 tutorialCell(所有其他单元格) ) 具有 tableView 并且可以垂直滚动其内容。

我想添加下一个行为:

  1. 用户滚动 tableView 内容并滑动到下一页
  2. 如果用户滑动回到他滚动的页面,我希望页面布局像最初设置的那样重新加载。

现在,如果用户滑动到他滚动的页面,他将看到他结束滚动的页面位置。

我建议 collectionView 内容可以在 didEndDisplaying 方法中重新加载:

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if indexPath.item != 0 {
        self.collectionView.reloadItems(at: [indexPath])
    }
}

但是使用这段代码我收到了一个奇怪的单元格行为:我可以在一个页面上向上滑动 tableView 并且出现的内容位置将在另一个页面上,但是一些页面可以加载正常的内容位置。这是一个 GIF:GIF

我也在 scrollViewDidScrollscrollViewDidEndDecelerating 中尝试了 collectionView.reloadData(),但收到了类似的行为。

您能否分享一些经验并帮助了解什么是适合我的案例的最佳做法?也许我应该找到一种根本不重新加载页面内容的方法,而是在约束中重新加载 imageView 高度锚?

尝试使用 DispatchQueue 方法:

if indexPath.item != 0 {
  DispatchQueue.main.async {
      self.collectionView.reloadData()
    }
  }

经过一些实验和信息研究,我得到了以下结果:

我稍微修改了我的初始目标:使用下面的代码,如果用户在滑动时将决定停留在当前页面,则不会重新加载数据。在其他情况下 - 重新加载。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OnboardingCell", for: indexPath) as! OnboardingCollectionViewCell

        // reset the current tableView position to initial one
        if cell.tableView.window != nil {
        cell.tableView.contentOffset = CGPoint.zero
        cell.tableView.layoutIfNeeded()
        cell.tableView.reloadData()
        }

        return cell
}


private var activePage = 0 {
    didSet {
        if activePage != oldValue {
            // the method will fire cellForItemAt code
            collectionView.reloadData()
        }
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    for cell in collectionView.visibleCells {
        activePage = collectionView.indexPath(for: cell)?.row ?? 0
    }
}

此外,如果您有导航控件,如上一个和下一个按钮,请不要忘记像这样重新加载数据:

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
    collectionView.reloadData()
}