在 Swift 中向下滚动时 UITableViewCell 的选择发生变化

Selection of UITableViewCell Changes when Scroll down in Swift

我正在使用 UITableView,我正在做的是在使用 [=16= 处的 UITableView 的 didSelectRow 函数点击单元格时更改单元格的颜色]cellForRowAt。困扰我的是,当我向下滚动或向上滚动时,我之前更改颜色的那些单元格已更改为其他单元格。这是我的代码:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

     let cell = myTableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell

     cell.backView.backgroundColor = .white

  return cell
} 

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

  let cell = myTableView.cellForRow(at: indexPath) as! TasksTableViewCell

  cell.backView.backgroundColor = UIColor(named: "primaryViewColor")
} 

有谁知道为什么会这样?有没有人有解决方案,当我点击时只有那些单元格改变颜色,当我向下滚动或向上移动时只有那些单元格有其他颜色?

据我了解,您 select 一个单元格,然后其他单元格看起来像是 selected?

如果是这样,我认为发生这种情况是因为您更改了单元格的背景颜色,而 tableView 和 collectionView 正在重用这些单元格,基本上保留了您更改的背景。

每次显示该单元格时都会调用 cellForRowAt。 您需要选择列表来保存选择的索引。

var listSelected: [Int] = []

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell
    
    cell.backView.backgroundColor = listSelected.contains(indexPath.row) ? UIColor(named: "primaryViewColor") : .white
    
    return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if listSelected.contains(indexPath.row) {
        listSelected = listSelected.filter{[=11=] != indexPath.row}
    } else {
        listSelected.append(indexPath.row)
    }
    
    tableView.reloadRows(at: [indexPath], with: .automatic)
    
}

TableViewCells一旦离开可见区域就会被重用。 这意味着一旦向上或向下滚动,其背景已着色的单元格将从视图层次结构中删除。如果相应的行再次滚动,函数 cellForRowAt 将再次为此 IndexPath 调用,单元格将变为白色背景。

最简单的方法是保存所选单元格的 IndexPaths,如果必须选择当前单元格,则在 cellForRowAt 函数中检查。

将以下变量添加到 viewController class:

var selectedIndexPaths = Set<IndexPath>()

并修改 tableView 委托方法:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = myTableView.dequeueReusableCell(withIdentifier: "TasksTableViewCell") as! TasksTableViewCell

    cell.backView.backgroundColor = (selectedIndexPaths.contains(indexPath) ? UIColor(named: "primaryViewColor") : .white)
    
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
    if selectedIndexPaths.contains(indexPath)
    {
        selectedIndexPaths.remove(indexPath)
    }
    else
    {
        selectedIndexPaths.insert(indexPath)
    }
    tableView.reloadRows(at: [indexPath], with: .none)
}

我遇到你看问题很多次了。即使使用和 iVar 可以解决问题,你也在混合“控制器”逻辑和“模型”逻辑。

我通常更喜欢在模型中移动“选择”状态。 假设您有一个 class “联系人”用于填充单元格数据(通常的 MVC 模式) 我补充:

class contact{
..
var selected = false
}

并且在电视委托方法中我使用应用选择,或者更好的是我在自定义单元格中使用自定义选择方法(例如在单元格中看到一个√元素) 作为奖励,多项选择是免费的,您还可以为下一个 运行 :)

保存当前选择

您可以使用

第 1 步:创建模型

class DemoModel {
  var isSelected: Bool = false
  var color: UIColor = .While
 }

第 2 步:并在表视图中

  var listDemo: [DemoModel] = [DemoModel(),...]

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let cell = myTableView.dequeueReusableCell(withIdentifier: 
   "TasksTableViewCell") as! TasksTableViewCell
    var obj = listDemo[indexPath.row]
   cell.backView.backgroundColor = obj.color

   return cell
 } 

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
   var obj = listDemo[indexPath.row]
   obj.color = UIColor(named: "primaryViewColor")
   tableView.reloadRows(at: [indexPath], with: .automatic)
}