当我试图折叠UITableView部分时,索引超出范围

问题描述:

在jeantimex关于如何展开/折叠部分here及其github的回答后,我添加了以下代码以在节点被轻敲时隐藏行:当我试图折叠UITableView部分时,索引超出范围

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),并试图利用另一部分,应用程序崩溃与错误:

fatal error: Index out of range

我做了一些调试打印的部分指标,并意识到,当我删除从我的数据对象时,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() 
+0

我注意到你正在从头文件'cell.section'中得到部分 - 是否可以这样呢,因为头文件正在被重用,而不是在崩溃时更新该部分? – sooper

+0

@sooper现在你提到它了,我认为可能是这样。当我删除第一个对象时,'cell.section'没有更新它的索引。 – iamhx

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

+0

删除该部分后,我在我的tableView中添加了'reloadData()',现在它工作... – iamhx

+0

这是另一种方式,我不确定你在折叠时还能得到你想要的动画吗? – sooper

+0

嗯,是的,当我移除第一部分时,似乎存在动画的一个问题...第二部分仅向上移动而不是部分和行。 – iamhx