【问题标题】:Expand and collapse multilevel sections in uitableview swift4在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

标签: ios swift uitableview collapse expand


【解决方案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
猜你喜欢
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 2014-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多