在uitableview swift4中展开和折叠多级部分

Posted

技术标签:

【中文标题】在uitableview swift4中展开和折叠多级部分【英文标题】:Expand and collapse multilevel sections in uitableview swift4 【发布时间】:2019-08-31 12:23:02 【问题描述】:

我想在 uitableview 中展开和折叠多级数组,如下所示

1 类 SubCat1 信息 1 信息 2 子类 2 信息 1 信息 2 SubCat3 信息 1 信息 2 二类 SubCat1 信息 1 信息 2

为此,我完成了以下代码。

struct CellData 
var opened = Bool()
var subCatTitle = String()
var subCatList = [String]()

struct MainModel 
var opened = Bool()
var categoryTitle = String()
var categoryList = [CellData]()
 

我已经列出来了

 @IBOutlet var expandableThreeStageTableView: UITableView!
    var arrayList = [CellData]()
    var expandableList = [MainModel]()

func loadData()
    arrayList.append(CellData(opened: false, subCatTitle: "SubCat1", subCatList: ["Info1","Info2","Info3"]))
    arrayList.append(CellData(opened: false, subCatTitle: "SubCat2", subCatList: ["Info1","Info2","Info3"]))
    arrayList.append(CellData(opened: false, subCatTitle: "SubCat3", subCatList: ["Info1","Info2"]))
    arrayList.append(CellData(opened: false, subCatTitle: "SubCat4", subCatList: ["Info1"]))

    expandableList.append(MainModel(opened: true, categoryTitle: "Cat1", categoryList: arrayList))
    expandableList.append(MainModel(opened: false, categoryTitle: "Cat2", categoryList: arrayList))
    expandableList.append(MainModel(opened: false, categoryTitle: "Cat3", categoryList: arrayList))

和delegate,datasource方法如下

extension TextFieldAsSearchVC : UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int 
        return expandableList.count

func tableView(_ tableView: UITableView, numberOfRowsInSection section: 
Int) -> Int 
        if expandableList[section].opened
            if expandableList[section].categoryList[section].opened
                return 
expandableList[section].categoryList[section].subCatList.count////which extra count should return here
            else
                print("COUNT ",expandableList[section].categoryList.count)
                return expandableList[section].categoryList.count + 
1///here +1 is for catname + subcatname

            
        else
            return 1
        
    

func tableView(_ tableView: UITableView, cellForRowAt indexPath: 
IndexPath) -> UITableViewCell 

        if indexPath.row == 0
            let cell = 
expandableThreeStageTableView.dequeueReusableCell(withIdentifier: 
"TextFieldAsSearchVCCell", for: indexPath) as! TextFieldAsSearchVCCell
            cell.lblValue.text = 
expandableList[indexPath.section].categoryTitle
            return cell
        else if indexPath.row <= 
expandableList[indexPath.section].categoryList.count
             let cell = 
expandableThreeStageTableView.dequeueReusableCell(withIdentifier: 
"SectionDataCell", for: indexPath) as! SectionDataCell
            cell.rowLabel.text = 
expandableList[indexPath.section].categoryList[indexPath.row - 
1].subCatTitle
            return cell
        
        else
            let cell = 
expandableThreeStageTableView.dequeueReusableCell(withIdentifier: 
"SectionDataCell", for: indexPath) as! SectionDataCell
  cell.rowLabel.text = 

 expandableList[indexPath.section].categoryList[indexPath.row].
subCatList[indexPath.row]//how to access rows in subcategories
            return cell
        
    

extension TextFieldAsSearchVC : UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: 
IndexPath) 
        if indexPath.row == 0
            if expandableList[indexPath.section].opened
                expandableList[indexPath.section].opened = false
                //now reload the section
                let sections = IndexSet(integer: indexPath.section)
                expandableThreeStageTableView.reloadSections(sections, 
with: .automatic)
            else
                expandableList[indexPath.section].opened = true
                //now reload sections
                let sections = IndexSet(integer: indexPath.section)
                expandableThreeStageTableView.reloadSections(sections, 
with: .automatic)
            

        else 
            if 
expandableList[indexPath.section].categoryList[indexPath.row].opened

expandableList[indexPath.section].categoryList[indexPath.row].opened = 
false
                expandableThreeStageTableView.reloadRows(at: 
[IndexPath(index: indexPath.row)], with: .automatic)
            else

expandableList[indexPath.section].categoryList[indexPath.row].opened = 
true
                expandableThreeStageTableView.reloadRows(at: 
[IndexPath(index: indexPath.row)], with: .automatic)
            
        
    

从上面的代码中,我可以展开和折叠类别,但不能展开子类别。当我尝试点击子类别时,它给了我一个错误

*** Terminating app due to uncaught exception 
'NSInternalInconsistencyException', reason: 'Invalid index path for use 
with UITableView. Index paths passed to table view must contain exactly 
two indices specifying the section and row. Please use the category on 
NSIndexPath in NSIndexPath+UIKitAdditions.h if possible.'

如何处理这种类型的逻辑?

【问题讨论】:

而不是为每个数据使用单元格在单元格内使用 stackview 并隐藏/显示 SubCats 【参考方案1】:

你得到的具体错误发生在这一行:

expandableThreeStageTableView.reloadRows(at: [IndexPath(index: indexPath.row)], with: .automatic)

IndexPath 需要 rowsection;你只提供一行。所以应该是这样的:

expandableThreeStageTableView.reloadRows(at: [IndexPath(row: indexPath.row, section: indexPath.section)], with: .automatic)

如果你真的只需要重新加载当前的indexPath,只需这样调用它:

expandableThreeStageTableView.reloadRows(at: [indexPath], with: .automatic)

这将解决您遇到的错误,但我不知道这是否解决了您的问题。

【讨论】:

thanx,第二个解决方案已经解决了一个错误。但现在如何在 'cellForRowAt' 方法中访问 SubCat[] 中的索引(行) 我相信您的代码中有多个错误。首先,在您的numbersOfSectionInTableView 实现中:您错误地计算了子类别的数量。你正在这样做:if expandableList[section].opened if expandableList[section].categoryList[section].opened 所以你永远不会到达像expandableList[0].categoryList[1] 这样的条目。您将不得不在这里重新考虑您的逻辑。一个IndexPath 只提供一个部分和一个行。你想要的是一个IndexPath,它有一个section、一个subsection和一个row

以上是关于在uitableview swift4中展开和折叠多级部分的主要内容,如果未能解决你的问题,请参考以下文章

无法在 Swift 中展开和折叠 TableViewCell

在 ios 中展开和折叠表格视图单元格

[转]VS中展开和折叠代码

VS中展开和折叠代码,还有其他快捷操作

当我在 ios 中展开和折叠 TableList 单元格时如何更改 UILabel 文本颜色

如何仅通过单击打开和折叠同一个 JQuery 手风琴