【问题标题】:Index is out of range when I tried to collapse a UITableView section当我尝试折叠 UITableView 部分时,索引超出范围
【发布时间】:2017-09-19 11:40:14
【问题描述】:

根据 jeantimex 关于如何展开/折叠部分here 和他的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()

【问题讨论】:

  • 我注意到您正在从标题 cell.section 获取该部分 - 可能是因为标题被重用,您在折叠时没有更新该部分?
  • @sooper 既然你提到了它,我想可能是这样。当我删除第一个对象时,cell.section 没有更新它的索引..

标签: ios swift uitableview


【解决方案1】:

您正在重用标题视图,但没有更新 section 以对应新的数据源结构。您需要更新折叠/展开后可见的标题视图。

【讨论】:

  • 删除该部分后,我在 tableView 中添加了 reloadData(),现在可以使用...
  • 那是另一种方式,虽然我不确定你在折叠时是否仍然可以获得你想要的动画?
  • 嗯,是的,当我删除第一部分时,动画似乎有一个问题......第二部分仅向上移动,而不是部分和行。
  • 这么想 - 您需要遍历可见单元格并重新配置它们以保留动画
  • 我该怎么做?我编辑了我的问题以包含我的删除部分代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-12
  • 2017-01-26
  • 2020-09-04
  • 1970-01-01
  • 2017-04-20
相关资源
最近更新 更多