iOS ColleCtionView 如何让cell 不重复创建并且只在展示的时候才创建

前言

使用 collectionView 一屏只展示一个 cell ,一次只加载当前 cell,还要能够缓存已加载过的 cell ,使 cell 不重复加载,听着好像就是将 collectionView 的复用机制禁用掉。用collectionView 实现这个需求,就出现了两个冲突点,一个是collectionView 会预加载后面的 cell ,另一个是会释放掉没在屏幕中显示的 cell 。
示例
iOS ColleCtionView 如何让cell 不重复创建并且只在展示的时候才创建_第1张图片

思路

  1. 将加载过的视图用一个字典存起来
  2. 当 cell 从重用池中取出来后,将字典中存放的对应视图 加载到 cell 上展示
  3. 当从字典中没有取到对应的视图时,就去创建新视图

主要实现代码

缓存的字典

var validViewDict:[Int:CommentView] = [:]

加载 cell

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.contentView.subviews.forEach { $0.removeFromSuperview()}
        
        if let validView = validViewDict[indexPath.item] {
            validView.frame = cell.contentView.bounds
            cell.contentView.addSubview(validView)
        }
        
        return cell
    }

创建视图时机

   func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard scrollView.isTracking || scrollView.isDragging else {
            return
        }
        let percent = scrollView.contentOffset.x/scrollView.bounds.size.width
        let maxCount = Int(round(scrollView.contentSize.width/scrollView.bounds.size.width))
        var leftIndex = Int(floor(Double(percent)))
        leftIndex = max(0, min(maxCount - 1, leftIndex))
        let rightIndex = leftIndex + 1;
        if percent < 0 || rightIndex >= maxCount {
            return
        }
        let remainderRatio = percent - CGFloat(leftIndex)

        if rightIndex == currentIndex {
            //当前选中的在右边,用户正在从右边往左边滑动
            if validViewDict[leftIndex] == nil && remainderRatio < (1 - initListPercent) {
                initListIfNeeded(at: leftIndex)
            }
            
        }else {
            //当前选中的在左边,用户正在从左边往右边滑动
            if validViewDict[rightIndex] == nil && remainderRatio > initListPercent {
                initListIfNeeded(at: rightIndex)
                currentIndex = rightIndex
            }
        }
        
    }

创建视图并存入字典

    func initListIfNeeded(at index: Int) {
      
        var existedView = validViewDict[index]
        if existedView != nil {
            //列表已经创建好了
            return
        }
        existedView = initValidView(initViewAt: index)
        guard let commentView = existedView else {
            return
        }
        
        validViewDict[index] = commentView
        
        let cell = collectView.cellForItem(at: IndexPath(item: index, section: 0))
        cell?.contentView.subviews.forEach { $0.removeFromSuperview() }
        commentView.frame = cell?.contentView.bounds ?? CGRect.zero
        cell?.contentView.addSubview(commentView)
    }

结语

使用字典保存加载的视图,每次加载 cell 时先移除子视图,再加载字典中的视图,避免了复用带来的界面展示内容不对的问题。在滚动代理 scrollViewDidScroll 中计算创建视图的时机,保证只创建当前展示的cell 的视图。这样我们就巧妙的实现了“如何让cell 不重复创建并且只在展示的时候才创建”。


感谢您的阅读和参与,HH思无邪愿与您一起在技术的道路上不断探索。如果您喜欢这篇文章,不妨留下您宝贵的赞!如果您对文章有任何疑问或建议,欢迎在评论区留言,我会第一时间处理,您的支持是我前行的动力,愿我们都能成为更好的自己!

你可能感兴趣的:(iOS,UIKit,ios,swift)