Swift 4 UITableView选中错误Cell问题求助
嘿,你的这两个问题其实都是UITableView的cell复用机制和cell实例化逻辑导致的,我给你一步步讲清楚原因和解决办法:
一、按钮点击设置cell背景色异常的问题
问题根源
- 未滚动时无反应:当第4行cell不在屏幕可见区域时,
MyTableView.cellForRow(at: myIndexPath)会返回nil——因为UITableView只会实例化当前可见的cell,不在视野里的cell要么还没创建,要么已经被回收进复用池了,所以设置背景色的代码根本没执行。 - 滚动后两个cell变色:UITableView的cell是复用机制,当第4行cell滚出屏幕,会被回收,之后第0行需要显示时,会复用这个已经被改成黄色背景的cell,所以第0行也会变成黄色,这就是你看到的“4和0一起变黄”的原因。
解决办法:用数据驱动UI
不要直接操作cell的UI属性,而是用变量记录选中状态,在cellForRowAt方法里根据状态渲染UI,这样不管cell是否复用,都能保持正确的显示效果:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var MyTableView: UITableView! var cellsArray = ["0" , "1" , "2" , "3" , "4" , "5" , "6" , "7"] // 新增变量记录选中的行,默认-1表示未选中 var selectedRow: Int = -1 override func viewDidLoad() { super.viewDidLoad() MyTableView.layer.borderWidth = 1 // 确保数据源和代理已设置(如果storyboard没关联的话) MyTableView.dataSource = self MyTableView.delegate = self } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return cellsArray.count // 别写死8,用数组长度更灵活 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = MyTableView.dequeueReusableCell(withIdentifier: "cells", for: indexPath) cell.textLabel?.text = cellsArray[indexPath.row] // 根据选中状态设置背景色 cell.backgroundColor = indexPath.row == selectedRow ? .yellow : .white return cell } @IBAction func MyButtonClick(_ sender: Any) { selectedRow = 4 // 记录选中第4行 // 只刷新对应行,不用刷新整个tableView MyTableView.reloadRows(at: [IndexPath(row: 4, section: 0)], with: .automatic) // 可选:让第4行滚动到可见区域 MyTableView.scrollToRow(at: IndexPath(row: 4, section: 0), at: .middle, animated: true) } }
二、计算单元格高度时崩溃的问题
问题根源
cellForRow(at:)只能获取当前屏幕上可见的cell,不在视图中的cell还没有被实例化,会返回nil,你直接用这个nil的cell去计算高度,自然会触发崩溃。
解决办法:绕开cell实例,直接计算内容高度
方法1:推荐用自动高度(最简单)
如果你的cell是用自动布局约束的(比如textLabel有上下左右的约束),可以直接开启UITableView的自动高度功能:
override func viewDidLoad() { super.viewDidLoad() // 开启自动高度 MyTableView.rowHeight = UITableView.automaticDimension // 设置预估高度(根据你的cell大概高度设置即可) MyTableView.estimatedRowHeight = 44 }
这样UITableView会自动根据cell的内容计算高度,完全不用你手动循环计算。
方法2:手动计算文本高度
如果需要手动计算,可以直接根据文本内容计算高度,不用依赖cell实例:
func calculateCellHeight(for text: String, cellWidth: CGFloat, font: UIFont) -> CGFloat { let textString = text as NSString // 计算文本占用的矩形区域 let boundingRect = textString.boundingRect( with: CGSize(width: cellWidth, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil ) // 向上取整避免高度不足 return ceil(boundingRect.height) } // 使用示例: let cellWidth = MyTableView.bounds.width - 16 // 减去cell的左右内边距 let targetText = cellsArray[某行索引] let height = calculateCellHeight(for: targetText, cellWidth: cellWidth, font: .systemFont(ofSize: 17))
内容的提问来源于stack exchange,提问作者WhatsMyPurpose
相关产品推荐
相关产品推荐

