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

UITableView滚动时图片重叠问题修复求助(附代码)

解决UITableView滚动时图片重叠的问题

这问题我太熟啦!你遇到的图片重叠本质是UITableViewCell复用机制在搞鬼——每次复用cell时你都往上面加新的UIImageView,旧的不会自动消失,滚来滚去就堆在一起了。给你两个靠谱的解决办法,优先推荐第一个(规范又省心):

方案一:自定义UITableViewCell(最佳实践)

自定义Cell能从根源解决复用带来的视图叠加问题,把UIImageView作为Cell的固定子视图,不用每次创建新的。

步骤1:创建自定义Cell类

import UIKit

class ATMTableViewCell: UITableViewCell {
    // 声明银行图标视图作为Cell的属性
    let bankIconImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.layer.cornerRadius = 20
        imageView.layer.masksToBounds = true
        imageView.contentMode = .scaleToFill
        imageView.translatesAutoresizingMaskIntoConstraints = false // 用AutoLayout需添加
        return imageView
    }()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        // 初始化时就把图标视图加到Cell的contentView上(比直接加cell更规范)
        contentView.addSubview(bankIconImageView)
        
        // 用AutoLayout设置布局(替换你原来的frame,适配不同屏幕)
        NSLayoutConstraint.activate([
            bankIconImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            bankIconImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            bankIconImageView.widthAnchor.constraint(equalToConstant: 70),
            bankIconImageView.heightAnchor.constraint(equalToConstant: 70)
        ])
        
        // 统一设置文本标签样式
        textLabel?.textColor = .black
        textLabel?.font = UIFont.systemFont(ofSize: 13)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

步骤2:修改tableView的cellForRow方法

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // 强转成自定义Cell
    let cell = tableView.dequeueReusableCell(withIdentifier: "atmCell", for: indexPath) as! ATMTableViewCell
    
    let atm = AtmList.instance.atms[indexPath.row]
    cell.textLabel?.text = atm.title
    cell.detailTextLabel?.text = atm.subtitle
    
    // 直接给Cell的图标视图赋值图片,不用再创建新视图
    cell.bankIconImageView.image = getBankImage(for: atm.title)
    
    return cell
}

// 把原来复杂的if-else抽成单独方法,代码更清晰
private func getBankImage(for bankTitle: String) -> UIImage? {
    // 用字典映射替代一堆if-else,维护起来更方便
    let bankImageMap: [String: String] = [
        "Wema": "wemaBank_pin",
        "Access": "AccessBank_pin",
        "Citi": "CitiBank_pin",
        "Diamond": "DiamondBank_pin",
        "Heritage": "HeritageBank_Pin",
        "Providus": "ProvidusBank_pin",
        "Fidelity": "FidelityBank_pin",
        "FCMB": "FCMB_pin",
        "Union": "UnionBank_pin",
        "GTBank": "GTBank_pin",
        "FirstBank": "FirstBank_pin",
        "Keystone": "KeystoneBank_pin",
        "Skye": "skyeBank_pin",
        "Eco": "ecoBank_pin",
        "Zenith": "ZenithBank_pin",
        "UBA": "UBA_pin",
        "Unity": "UnityBank_pin",
        "Stanbic": "St..." // 此处你原代码图片名未写完,自行补全
    ]
    
    // 根据标题前缀匹配对应图片
    for (key, imageName) in bankImageMap {
        if bankTitle.hasPrefix(key) {
            return UIImage(named: imageName)
        }
    }
    return nil // 无匹配时返回空
}

方案二:给UIImageView加Tag,复用现有视图(快速临时解决方案)

如果不想自定义Cell,也可以每次复用Cell时,先找有没有已存在的图标视图,有就复用,没有再创建:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "atmCell", for: indexPath)
    
    let atm = AtmList.instance.atms[indexPath.row]
    cell.textLabel?.text = atm.title
    cell.textLabel?.textColor = .black
    cell.textLabel?.font = UIFont.systemFont(ofSize: 13)
    cell.detailTextLabel?.text = atm.subtitle
    
    // 定义固定Tag值,用于查找已存在的视图
    let iconTag = 1001
    var cellImage: UIImageView!
    
    // 优先复用已有视图
    if let existingImageView = cell.viewWithTag(iconTag) as? UIImageView {
        cellImage = existingImageView
    } else {
        // 无视图时再创建并添加
        cellImage = UIImageView(frame: CGRect(x: 290, y: 39, width: 70, height: 70))
        cellImage.layer.cornerRadius = 20
        cellImage.layer.masksToBounds = true
        cellImage.contentMode = .scaleToFill
        cellImage.tag = iconTag // 设置Tag,方便下次复用查找
        cell.addSubview(cellImage)
    }
    
    // 图片匹配逻辑(可替换为上面的字典映射)
    if let firstChar = cell.textLabel?.text?.first {
        switch firstChar {
        case "W":
            cellImage.image = UIImage(named: "wemaBank_pin")
        case "A":
            cellImage.image = UIImage(named: "AccessBank_pin")
        case "C":
            cellImage.image = UIImage(named: "CitiBank_pin")
        // 剩余匹配逻辑自行补全...
        default:
            cellImage.image = nil
        }
    }
    
    return cell
}

为啥原来的代码会重叠?

UITableView采用Cell复用池机制:当Cell滚出屏幕时会被放入复用池,下次需要时直接取出复用。你原来的代码每次调用cellForRowAt都新建一个UIImageView并执行addSubview,导致复用的Cell上叠加了N个UIImageView,滚动时就出现了图片重叠的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 08:57:36