UITableView滚动异常:单元格文本重叠问题求助(Swift无Storyboard)
UITableViewCell文本重叠问题的解决方案
问题根源
你在tableView(_:cellForRowAt:)方法中,每次都会创建5个新的UILabel并添加到复用的cell上。由于UITableView会复用滚出屏幕的cell,当cell被再次调用时,之前添加的Label并未被移除,新Label叠在旧Label上方,最终导致文本重叠的层叠现象。
推荐解决方案:自定义UITableViewCell
这是UITableView开发的标准实践,既解决复用冲突,也提升代码可维护性。
步骤1:创建自定义Cell类
继承UITableViewCell,将所有需要的Label声明为类属性,并在初始化时完成样式设置与视图添加:
class CustomProductCell: UITableViewCell { // 初始化各个Label let labelIdProd: UILabel = { let label = UILabel(frame: CGRect(x: 25, y: 7, width: 40, height: 30)) label.textColor = .systemBlue // 替换为你的colorTextinCell return label }() let labelTextProd: UILabel = { let label = UILabel(frame: CGRect(x: 75, y: 7, width: 85, height: 30)) label.textColor = .systemBlue return label }() let labelAmountProd: UILabel = { let label = UILabel(frame: CGRect(x: 170, y: 7, width: 40, height: 30)) label.textColor = .systemBlue return label }() let labelPriceLVL2Prod: UILabel = { let label = UILabel(frame: CGRect(x: 220, y: 7, width: 40, height: 30)) label.textColor = .systemBlue return label }() let labelAmountAndPriceVLV2Prod: UILabel = { let label = UILabel(frame: CGRect(x: 270, y: 7, width: 60, height: 30)) label.textColor = .systemBlue return label }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) // 设置Cell基础样式 backgroundColor = .systemGray5 layer.cornerRadius = 8 // 替换为你的cornerRadiusCell layer.borderWidth = 2 layer.borderColor = CGColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1) accessoryType = .detailButton tintColor = .systemBlue // 将Label添加到contentView(官方推荐的Cell子视图容器) contentView.addSubview(labelIdProd) contentView.addSubview(labelTextProd) contentView.addSubview(labelAmountProd) contentView.addSubview(labelPriceLVL2Prod) contentView.addSubview(labelAmountAndPriceVLV2Prod) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
步骤2:修改cellForRowAt方法
将复用的cell强转为自定义Cell类型,直接更新已有Label的文本,无需重复创建视图:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: tabViewCell, for: indexPath) as! CustomProductCell let currentItem = allItems[indexPath.section].listP[indexPath.row] // 格式化ID文本 let numbIdForCell: String if currentItem.id < 10 { numbIdForCell = "00\(currentItem.id)" } else if currentItem.id >= 10 { numbIdForCell = "0\(currentItem.id)" } else { numbIdForCell = "\(currentItem.id)" } // 更新各个Label内容 cell.labelIdProd.text = numbIdForCell cell.labelTextProd.text = currentItem.namePrdct cell.labelAmountProd.text = String(currentItem.amoutn) cell.labelPriceLVL2Prod.text = String(format: "%.1f", currentItem.priceLevel2) let totalPrice = Double(currentItem.amoutn) * currentItem.priceLevel2 cell.labelAmountAndPriceVLV2Prod.text = String(format: "%.1f", totalPrice) return cell }
步骤3:注册自定义Cell
在ViewController的viewDidLoad方法中注册自定义Cell:
override func viewDidLoad() { super.viewDidLoad() // 其他初始化代码... tableView.register(CustomProductCell.self, forCellReuseIdentifier: tabViewCell) }
临时应急方案(不推荐)
如果不想重构自定义Cell,可在每次添加新Label前移除cell上的所有旧Label,但这种方法易误删其他视图,且影响性能:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: tabViewCell, for: indexPath) // 移除所有旧Label cell.contentView.subviews.forEach { if $0 is UILabel { $0.removeFromSuperview() } } // 原有的cell样式设置、Label创建与添加代码... return cell }
内容的提问来源于stack exchange,提问作者Vladislav Zhelezniak
相关产品推荐
相关产品推荐

