当我试图崩溃的uitable视图部分时,索引超出了范围



遵循Jeantime X的答案,介绍了如何在此处展开/折叠部分和他的github,我添加了以下代码,以在挖掘部分时隐藏行:

struct Person {
    //this is my data
    let name: String
    var item: [(itemName: String, price: Decimal)]
    var collapsed: Bool!
    init(name: String, item: [(itemName: String, price: Decimal)], collapsed: Bool = false) {
        self.name = name
        self.item = item
        self.collapsed = collapsed
    }
}
class TableSectionHeader : UITableViewHeaderFooterView {
    //this is my custom header section
    var delegate: CollapsibleTableViewHeaderDelegate?
    var section: Int = 0
    @IBOutlet weak var lblPerson: UILabel!
    @IBOutlet weak var lblTotal: UILabel!
    func tapHeader(_ gestureRecognizer: UITapGestureRecognizer) {
        guard let cell = gestureRecognizer.view as? TableSectionHeader else {
            return
        }
        delegate?.toggleSection(self, section: cell.section)
        print(cell.section)
    }
}
protocol CollapsibleTableViewHeaderDelegate {
    func toggleSection(_ header: TableSectionHeader, section: Int)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return personArray[indexPath.section].collapsed! ? 0 : 44.0
}

在我的viewForHeaderInSection委托中,我添加了UITapGestureRecognizer

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let cell = billTableView.dequeueReusableHeaderFooterView(withIdentifier: "TableSectionHeader")
    let header = cell as! TableSectionHeader
    header.section = section
    header.delegate = self
    header.lblPerson.text = structArray[section].name
    header.lblTotal.text = SplitBill().displayIndividualTotal(person: structArray, section: section)
    header.addGestureRecognizer(UITapGestureRecognizer(target: header.self, action: #selector(header.tapHeader(_:))))
    return cell
}

这些部分能够完美崩溃/扩展,但是我有一个按钮可以删除一个部分,当我删除第一部分(0(并尝试点击另一部分时,该应用程序崩溃了:

致命错误:索引超出范围

我进行了一些调试以打印部分索引,并意识到当我从数据中删除对象时,toggleSection函数仍在持有第二部分的索引(1(:

extension BillForm: CollapsibleTableViewHeaderDelegate {
    func toggleSection(_ header: TableSectionHeader, section: Int) {
        print(section) //index is 1 although I have removed the first object
        let collapsed = !personArray[section].collapsed
        // Toggle collapse
        personArray[section].collapsed = collapsed
        // Adjust the height of the rows inside the section
        billTableView.beginUpdates()
        for i in 0 ..< personArray[section].item.count {
            billTableView.reloadRows(at: [IndexPath(row: i, section: section)], with: .automatic)
        }
        billTableView.endUpdates()
    }
}

我仍然有点困惑,并且对Jeantimex的代码不太熟悉,因此我不确定在哪里解决此问题。谁能帮我吗?

编辑:

在我的删除部分按钮上设法与reloadData()一起使用。

for i in (0..<self.personArray[row].item.count).reversed() {
    let rowIndex = IndexPath(row: i, section: row)
    self.personArray[row].item.remove(at: i) //remove rows first
    self.billTableView.deleteRows(at: [rowIndex], with: .right)
}
self.personArray.remove(at: row) //then remove section
self.billTableView.deleteSections(IndexSet(integer: row), with: .right)
self.billTableView.reloadData()

您要重复使用标头视图,但不更新section以对应于新的数据源结构。您需要更新崩溃/扩展后可见的标头视图。

最新更新