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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:07:38