showing the Rows when a Section header is selected

265 views Asked by At

I have a view controller which contain a table view. I want to add the ability to show the ROW whenever the section header is pressed, and vice-versa(expandable table view).

the code below shows the code that I have written for my table view:

  func numberOfSections(in tableView: UITableView) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let cell = tableview.dequeueReusableCell(withIdentifier: "ReportHeaderCell") as! ReportHeaderTableViewCell
        cell.IMG.image = #imageLiteral(resourceName: "Cost_Arrow")
        cell.BillHeaderTitle.text = data[section].billType
        cell.totalValue.text = data[section].totalValue?.addComma
        cell.dateLbl.text = data[section].billDate

        let animationView = LOTAnimationView(name: "CloseOpen")
        animationView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
        animationView.loopAnimation = false
        animationView.autoReverseAnimation = false
        animationView.play(fromProgress: 0, toProgress: 0.0, withCompletion: nil)
        cell.openCloseView.addSubview(animationView)
        animationView.play()

        cell.MainView.addTapGesture {
            print("header is tapped")
            if self.isOpen[section] == true
            {
                print("header is open")
                self.isOpen[section] = false
                // we'll try to close the section first by deleting the rows
                var indexPaths = [IndexPath]()
                for row in self.data[section].units.indices {
                    print(0, row)
                    let indexPath = IndexPath(row: row, section: section)
                    indexPaths.append(indexPath)


//                    tableView.deleteRows(at: indexPaths, with: .bottom)
//                    tableview.reloadData()
                    self.tableview.deleteRows(at: indexPaths, with: .top)


                }
                let animationView = LOTAnimationView(name: "CloseOpen")
                animationView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
                animationView.loopAnimation = false
                animationView.autoReverseAnimation = false
                animationView.animationSpeed = 2.5
                animationView.play(fromProgress: 1, toProgress: 0.0, withCompletion: nil)
                cell.openCloseView.addSubview(animationView)
                animationView.play()
            }
            else
            {
                print("header is close")

                self.isOpen[section] = true
                //let's open it
                // we'll try to close the section first by deleting the rows
                var indexPaths = [IndexPath]()
                for row in self.data[section].units.indices
                {
                    print(0, row)
                    let indexPath = IndexPath(row: row, section: section)
                    indexPaths.append(indexPath)

//                    tableView.insertRows(at: indexPaths, with: .top)
                    self.tableview.insertRows(at: indexPaths, with: .top)

//                    tableview.reloadData()
                    let animationView = LOTAnimationView(name: "CloseOpen")
                    animationView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
                    animationView.loopAnimation = false
                    animationView.autoReverseAnimation = false
                    animationView.play(fromProgress: 0, toProgress: 1, withCompletion: nil)
                    animationView.animationSpeed = 2.5
                    cell.openCloseView.addSubview(animationView)
                    animationView.play()
                }
        }


        }
        return cell

    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if self.isOpen[section] == true
        {
        print(data[section].units.count)
            return data[section].units.count
        }
        else
        {
            return 0
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableview.dequeueReusableCell(withIdentifier: "ReportCell") as! ReportTableViewCell
//
//        if indexPath.row != 0
//        {
        cell.UnitName.text = data[indexPath.section].units[indexPath.row]?.unitName
//            print(data[indexPath.section].units[indexPath.row]?.unitName!)
        cell.Unitdebit.text = data[indexPath.section].units[indexPath.row]?.debit?.addComma
            if indexPath.row == data.count - 1
            {
                cell.DownRightView.isHidden = true
            }

//        }
//        else{}

        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if isOpen[indexPath.section] == true
        {
            self.isOpen[indexPath.section] = false
            let section = IndexSet.init(integer: indexPath.section)
            tableView.reloadSections(section, with: .top)
        }
        else
        {
            self.isOpen[indexPath.section] = true
            let section = IndexSet.init(integer: indexPath.section)
            tableView.reloadSections(section, with: .bottom)
        }
    }


    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 60
    }
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 90
    }

SOLVED: there is a very big problem here!! and which is:

for example, we have four sections in our table view and the user selects number 2. as soon as the user selects number 2, section number 3 and 4 are disappearing!!!

to clarify, the sections with a greater number of the selected section will be disappeared!

does anybody have any IDEA what am I doing wrong here??

THIS ERROR IS STILL REMAINING: could anyone help!!! I'm stuck

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).

the json related to the error

    [
  {
    "totalValue" : 11,
    "units" : [
      {
        "unitName" : "jack",
        "debit" : 11,
        "unit" : 1
      },
      {
        "unitName" : "jack1",
        "debit" : 11,
        "unit" : 2
      }
    ],
    "billType" : "glocery",
    "billDate" : "1998\/08\/20",
    "billId" : 29049
  }
1

There are 1 answers

0
Am1rFT On

Put the insert and delete out of the for loop that should solve the problem