Swift开发:UITableView单元格滚动后颜色重置问题求助
解决TableView滚动后单元格颜色恢复的问题
这个问题的核心原因是UITableView的单元格复用机制:当你滚动TableView时,离开屏幕的单元格会被回收复用给新进入屏幕的行。你目前只在滑动操作时临时修改了单元格的颜色,但没有在cellForRowAt方法中根据selectedHobbies的状态来设置正确的颜色,所以复用的时候单元格就回到了默认的青色。
下面是具体的修复步骤:
1. 修复单元格复用逻辑
首先,不要每次都创建新的UITableViewCell,要用复用标识符获取可复用的单元格(这是TableView的最佳实践,也能避免复用带来的状态混乱):
// 先在viewDidLoad里注册单元格 override func viewDidLoad() { super.viewDidLoad() // ... 原有其他代码 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "HobbyCell") resultController.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "HobbyCell") } // 修改cellForRowAt方法 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "HobbyCell", for: indexPath) let currentHobby: String if tableView == resultController.tableView { currentHobby = filteredHobbies[indexPath.row] } else { currentHobby = hobbies[indexPath.row] } cell.textLabel?.text = currentHobby // 关键:根据selectedHobbies设置单元格背景色 if selectedHobbies.contains(currentHobby) { cell.backgroundColor = .white } else { cell.backgroundColor = .cyan } return cell }
2. 修改滑动操作逻辑,更新后刷新对应行
在添加或移除爱好后,不要直接修改单元格颜色,而是通过reloadRows刷新对应行,这样TableView会重新调用cellForRowAt,根据最新的selectedHobbies状态设置正确的颜色:
修改importantAction方法:
func importantAction(at indexPath: IndexPath) -> UIContextualAction { var hobby = "" let searchText = searchController.searchBar.text ?? "" if searchText.isEmpty { hobby = hobbies[indexPath.row] } else { hobby = filteredHobbies[indexPath.row] } let action = UIContextualAction(style: .normal, title: "") { [weak self] (action, view, completion) in guard let self = self else { completion(true) return } if self.selectedHobbies.contains(hobby) { action.title = "Add Hobby" action.backgroundColor = .gray } else { self.selectedHobbies.append(hobby) self.numberSelected += 1 action.title = "Added" action.backgroundColor = .green // 刷新对应行 let targetTable = tableView == self.resultController.tableView ? self.resultController.tableView : self.tableView targetTable.reloadRows(at: [indexPath], with: .automatic) if self.numberSelected >= 10 { self.performSegue(withIdentifier: "segue1", sender: nil) } } print(self.selectedHobbies) completion(true) } // 初始化时根据状态设置按钮样式 if selectedHobbies.contains(hobby) { action.title = "Add Hobby" action.backgroundColor = .gray } else { action.title = "Add Hobby" action.backgroundColor = .green } return action }
修改removeAction方法:
func removeAction(at indexPath: IndexPath) -> UIContextualAction { var hobby = "" let searchText = searchController.searchBar.text ?? "" if searchText.isEmpty { hobby = hobbies[indexPath.row] } else { hobby = filteredHobbies[indexPath.row] } let action = UIContextualAction(style: .normal, title: "") { [weak self] (action, view, completion) in guard let self = self else { completion(true) return } if self.selectedHobbies.contains(hobby) { self.selectedHobbies = self.selectedHobbies.filter{$0 != hobby} self.numberSelected -= 1 action.title = "Removed" action.backgroundColor = .red // 刷新对应行 let targetTable = tableView == self.resultController.tableView ? self.resultController.tableView : self.tableView targetTable.reloadRows(at: [indexPath], with: .automatic) } else { action.title = "Remove Hobby" action.backgroundColor = .gray } print(self.selectedHobbies) completion(true) } // 初始化时根据状态设置按钮样式 if selectedHobbies.contains(hobby) { action.title = "Remove Hobby" action.backgroundColor = .red } else { action.title = "Remove Hobby" action.backgroundColor = .gray } return action }
额外优化建议
- 把全局变量
selectedHobbies和numberSelected放到TableViewController类内部,避免全局变量带来的状态混乱。 - 用
searchController.searchBar.text ?? ""替代强制解包,避免空文本导致的崩溃。 - 可以考虑创建一个爱好模型类(比如
Hobby),包含name和isSelected属性,这样比用数组存储选中名字更直观,也更容易维护。
内容的提问来源于stack exchange,提问作者techgeek14
相关产品推荐
相关产品推荐

