UITableView实现选中全部子项时自动选中首项并取消子项选中
问题:UITableView 选中状态自动切换逻辑实现
我有一个UITableView,单元格标题从服务器获取,标题为字符串数组,显示内容如下:
- All data
- List item
- Coffees
- Teas
- Dessert
- Main dishes
目前已实现单个单元格的选中/取消选中功能,运行正常。现需实现:当List item、Coffees、Teas、Dessert、Main dishes这5个单元格全部被选中时,自动取消它们的选中状态,并自动选中第一个“All data”单元格。
已知需在tableView的didSelectRowAt方法中编写逻辑,但不清楚正确的逻辑实现方式,附上当前代码示例:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let isSelected = arrayOfTitles[indexPath.row].isSelected else {arrayOfTitles[indexPath.row].isSelected = true; return} arrayOfTitles[indexPath.row].isSelected = !isSelected filter?.values?[indexPath.row].isSelected = !isSelected for i in 1..<arrayOfTitles.count { if arrayOfTitles[i].isSelected == isSelected { arrayOfTitles[0].isSelected = isSelected arrayOfTitles[i].isSelected = !isSelected } } }
解决方案
你的现有代码逻辑存在混乱,没有正确判断所有子项是否全选,以下是修正后的实现:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 处理当前点击单元格的选中状态切换 let currentItem = arrayOfTitles[indexPath.row] currentItem.isSelected = !(currentItem.isSelected ?? false) // 同步filter中的状态 filter?.values?[indexPath.row].isSelected = currentItem.isSelected // 检查第2到第6项(索引1到5)是否全部被选中 let allSubItemsSelected = arrayOfTitles[1...5].allSatisfy { $0.isSelected == true } if allSubItemsSelected { // 取消所有子项的选中状态 for i in 1...5 { arrayOfTitles[i].isSelected = false filter?.values?[i].isSelected = false } // 选中第一个"All data"项 arrayOfTitles[0].isSelected = true filter?.values?[0].isSelected = true // 刷新tableView同步UI tableView.reloadData() return } // 非全选情况,仅刷新当前点击的单元格 tableView.reloadRows(at: [indexPath], with: .automatic) }
逻辑说明:
- 先处理当前点击单元格的选中状态切换,同步更新
filter中的对应状态; - 使用
allSatisfy方法直接判断索引1到5的所有项是否都处于选中状态,逻辑简洁清晰; - 一旦满足全选条件,批量修改子项和第一项的选中状态,然后刷新整个tableView确保UI同步;
- 非全选情况下,只刷新当前点击的单元格,避免不必要的UI更新,优化性能。
内容的提问来源于stack exchange,提问作者developer
相关产品推荐
相关产品推荐

