You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UICollectionView Cell滚动后评分图标消失,如何持久显示?

UICollectionView滚动后评分图标消失的解决方案

问题原因

核心问题是UICollectionView的Cell复用机制:当Cell滚出屏幕后会被回收复用,你当前仅在Cell内部保存评分状态,未将状态同步到数据源模型中;同时prepareForReuse方法清空了btnRate.image,导致复用Cell时无法恢复之前的评分状态。

解决步骤

  1. 给数据源模型添加评分状态属性:将评分结果存储在数据源(Responder)中,而非仅保存在Cell内部
  2. 在Cell的configure方法中恢复评分状态:每次Cell被复用配置时,根据模型的评分状态显示对应图标
  3. 修改评分按钮逻辑:点击评分按钮时,更新对应数据源模型的评分状态,确保状态持久化

修改后的代码示例

1. 扩展数据源模型,添加评分状态

// 定义评分类型枚举
enum RatingType: String {
    case none, good, hate
}

// 修改Responder模型,新增评分状态属性
class Responder {
    var id: String?
    var packShot: PackShot? // 保留原有属性
    var ratingType: RatingType = .none // 新增评分状态字段
}

2. 修改ViewController代码

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reUseMoviesCellID, for: indexPath) as! MoviesCollectionCell
    let currentMovie = movieObj[indexPath.row]
    
    // 绑定按钮ID
    cell.btnSmallGoodRate.id = currentMovie.id ?? ""
    cell.btnSmallHateRate.id = currentMovie.id ?? ""
    
    // 修改tapHandler,传递评分类型用于更新数据源
    cell.tapHandler = { ratingType in
        Commons.userGlobalRate += 1
        self.lblRated.text = "\(Commons.userGlobalRate) rated"
        self.ratedView.backgroundColor = .ratedGoldColour
        if Commons.progressBarValue < 1 {
            Commons.progressBarValue += 0.2
            self.ratedTrackBarView.setProgress(Commons.progressBarValue, animated: true)
        }
        // 更新数据源的评分状态
        currentMovie.ratingType = ratingType
    }
    
    // 配置Cell,包含评分状态恢复
    cell.configure(with: currentMovie)
    return cell
}

3. 修改MoviesCollectionCell代码

class MoviesCollectionCell: UICollectionViewCell {
    
    // 修改tapHandler为带参数类型,传递评分类型
    var tapHandler: ((RatingType)->())?
    
    // 保留原有UI组件定义...
    
    override func prepareForReuse() {
        super.prepareForReuse()
        movieImage.image = nil
        // 重置评分相关UI状态
        btnRate.alpha = 0
        btnRate.image = nil
        movieOverlay.alpha = 0
        btnSmallGoodRate.alpha = 0
        btnSmallHateRate.alpha = 0
        removeOverlay.alpha = 0
    }
    
    func configure(with res: Responder){
        movieImage.sd_setImage(with: URL(string: res.packShot?.thumbnail ?? ""), placeholderImage: UIImage(named: "ImagePlaceholder"))
        
        // 根据模型的评分状态恢复UI
        switch res.ratingType {
        case .good:
            btnRate.alpha = 1
            btnRate.image = UIImage(named: "goodRate")
        case .hate:
            btnRate.alpha = 1
            btnRate.image = UIImage(named: "HateIt")
        case .none:
            btnRate.alpha = 0
            btnRate.image = nil
        }
    }
    
    // 保留原有的长按、关闭方法...
    
    @objc func hateItem(_ sender: UIButton){
        guard let gestureVariable = sender as? ButtonRating else{
            return
        }
        let movieID = gestureVariable.id
        print("Hate movie ID ", movieID)
        // 隐藏评分按钮面板
        btnSmallHateRate.alpha = 0
        btnSmallGoodRate.alpha = 0
        removeOverlay.alpha = 0
        // 设置当前Cell的评分UI
        btnRate.alpha = 1
        btnRate.image = UIImage(named: "HateIt")
        // 通知VC更新数据源
        tapHandler?(.hate)
    }
    
    @objc func goodItem(_ sender: UIButton){
        guard let gestureVariable = sender as? ButtonRating else{
            return
        }
        let movieID = gestureVariable.id
        print("Good movie ID ", movieID)
        // 隐藏评分按钮面板
        btnSmallHateRate.alpha = 0
        btnSmallGoodRate.alpha = 0
        removeOverlay.alpha = 0
        // 设置当前Cell的评分UI
        btnRate.alpha = 1
        btnRate.image = UIImage(named: "goodRate")
        // 通知VC更新数据源
        tapHandler?(.good)
    }
    
    // 保留其他原有代码...
}

关键说明

  • 所有状态必须保存在数据源模型中,Cell仅负责根据模型渲染UI,避免复用导致状态丢失
  • configure方法是Cell的唯一配置入口,所有UI状态都要在这里根据模型设置
  • prepareForReuse负责重置Cell的初始状态,避免旧状态干扰新数据的展示

内容的提问来源于stack exchange,提问作者KwameB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 04:15:49