iOS UITableView 以编程方式选择多个单元格并显示检查时出现问题

iOS having issues with UITableView programmatically selecting multiple cells and displaying a check

我有一个应用程序,用户可以在 UITableView 上 select 多个项目。然后他们点击添加按钮并更新数组。然后它倒回到之前的 VC。现在当用户点击返回更新 selections.

我希望对单元格进行 select 编辑并检查 accessoryStyle。到目前为止,一切正常,除了 selecting 单元格。所以数组将有几个选项,那些 selected 选项有复选标记。

当用户 select 一个单元格时,didSelect 应该将该选项添加到数组中(如果尚未添加)。当用户 de-selects 时,单元格 didDeselect 被调用并且该项目从数组中删除。 (也可以显示或不显示复选标记)。

现在的问题是当用户返回带有复选标记的单元格时未 selected 并且当他们 select 销售它时调用 didSelect 而不是 didDeselect。我发现的大多数教程和帮助似乎只适用于单个 select,而且我似乎无法突出显示单元格。请参阅图片以获得更多说明。

新问题/更新

最初的问题已经解决了。现在,当我 select 数组的元素 0 时,数组的 10 元素也更改了附件。这也逐渐重复。

这是我的阵列设置

let expansionBayList: [ExpansionBay] = [ArcaneLaboratory(), CargoHold(), EscapePods(), GuestQuarters(), HangarBay(),
                            LifeBoats(), MedicalBay(), PassengerSeating(), PowerCoreHousing(), RecreationSuiteGym(),
                            RecreationSuiteTrividDen(), RecreationSuiteHAC(), ScienceLab(), SealedEnviromentChamber(), ShuttleBay()]

因此,当我从列表中 select 奥术实验室时,Recreation Suite Trivid Den 也有一个复选标记,但未被 select 编辑。我假设这与 reuseIdentifier 有关?我假设我需要在滚动时清除它?

我尝试了以下方法(我在 cellForRowAt 中厌倦了它):

cell.isSelected = true
cell.isHighlighted = true

我还尝试了以下(在 viewDidLoad 中):

multiSelectTbl.allowsMultipleSelection = true
multiSelectTbl.allowsSelectionDuringEditing = true

这是用户第一次更新此屏幕。

这是当用户 selects Expansion Bay 在上一个屏幕上更新和进行更改时发生的情况。我如何才能使每个带有复选标记的单元格也像第一张图片一样突出显示?

有一个数组确定哪些框应该有复选标记。

要为您应该使用的行设置初始选定状态 tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)

我不知道 UITableView 选择的具体工作原理,但 UITableViewCell 上的 isSelected 标志似乎只是用于渲染 因此,如果您在单元格上设置 isSelected,则 tableView 不会被选中并调用 didSelect 而不是 didDeselect

覆盖自定义 table 视图单元格中的 setSelected 方法 class,

并对 select 个单元格使用 tableview.selectRow(at:) 函数。

使用 tableView.indexPathsForSelectedRows 在 table.

中获取 selected indexPaths

这是一个很好的实现。 https://github.com/yonat/SelectionList

回复新问题: 请按照步骤操作。

  1. viewDidLoadviewWillAppear 方法

        var itemsToBeSelected: [String]?
        var listItems: [String]? 
    
        ....
        override func viewDidLoad() {
            super.viewDidLoad()
            if let selected = self.itemsToBeSelected, let listItems = self.listItems {
                selected.forEach { (item) in
                if let index = listItems.index(of: item) {
                    let indexPath = IndexPath(item: index, section: 0)
                    self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
                }
            }
        }        
    

    self.itemsToBeSelected 表示当视图控制器出现时,它们需要在列表中默认被 selected。在上面的例子中它只是一个 String 的数组。

  2. cellForRowAt方法

    No need to call cell.isSelected = true/false or cell.isHighlighted = true/false

    如果单元格是自定义单元格,您可以只将内容应用于单元格。在自定义单元格 class 中,只需重写 setSelected 方法。

    class ExpansionBayCell {
        ....
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            self.checkBox.isChecked = self.isSelected
        }
    }
    
  3. 何时获取所有 selected 值并关闭视图控制器

    func btnDonePressed() {        
        guard let indexPaths = tableView.indexPathsForSelectedRows else {
            btnBackPressed()            
            return
        }
    
        let items = indexPaths.map { self.listItems[[=12=].row] }
        completion(items)
        btnBackPressed()
    }
    

在这种情况下,您首先需要添加对多选的支持,以便首先将 allowsMultipleSelectionallowsMultipleSelectionDuringEditing 设置为 true。

例如:-

self.tableView.allowsMultipleSelection = true
self.tableView.allowsMultipleSelectionDuringEditing = true

然后创建一个 CustomTableViewCell,它将子类化 UITableViewCell。 覆盖 setSelected 方法。

例如:-

class CustomTableViewCell: UITableViewCell {
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.selectionStyle = .none
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        self.accessoryType = selected ? .checkmark : .none
    }
}

现在您可以在 cellForRow 方法中使用您的自定义单元格:

let cell = tableView.dequeueReusableCell(withIdentifier: "cell", 
    for: indexPath) as? CustomTableViewCell
cell.setSelected(isSelected, animated: true)