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
}
Put the insert and delete out of the for loop that should solve the problem