0

I have an expandable and collapsible section in my tableview cell for days of the week. When you click the open button to expand the section the button changes state to close and you can click it again to collapse. However, if you open multiple sections and start scrolling in the tableview those sections close and open but the button state does not change back to close once all the sections have reopened from scrolling.

I was doing some research and it seems like the state is not being saved. Is there any way of saving the state of those buttons using dequeuereusableheaderfooterview() in the viewForHeaderInSection? Or does it have to be done in the cellForRowAt function?

var barDeals: [ExpandableDealsStruct] = []


@IBOutlet weak var daysTable: UITableView!

override func viewDidLoad()
{
    super.viewDidLoad()

    daysTable.dataSource = self
    daysTable.delegate = self

}


func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{

    let view = UIView()
    view.backgroundColor = .black

    let headerLabel = UILabel()
    let button = UIButton(type: .system)

    let headerList = DaysService.instance.getHeader()
    headerLabel.textColor = .white
    headerLabel.font = UIFont.boldSystemFont(ofSize: 20)
    headerLabel.text = headerList[section]

    button.setTitle("Open", for: .normal)
    button.setTitleColor(.white, for: .normal)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
    button.addTarget(self, action: #selector(handleOpenClose), for: .touchUpInside)
    button.tag = section

    headerLabel.frame = CGRect(x: 5, y: 7.5, width: 150, height: 25)
    button.frame = CGRect(x: 150, y: 7.5, width: 150, height: 25)


    view.addSubview(headerLabel)
    view.addSubview(button)

    return view
}

@objc func handleOpenClose(button: UIButton)
{
    let section = button.tag

    self.daysTable.beginUpdates()
    var indexPaths = [IndexPath]()

    for deals in self.barDeals[section].deals.indices
    {
        let indexPath = IndexPath(row: deals, section: section)
        indexPaths.append(indexPath)
    }

    let isExpanded = self.barDeals[section].isExpanded
    self.barDeals[section].isExpanded = !isExpanded

    button.setTitle(!isExpanded ? "Close" : "Open", for: .normal)

    if isExpanded
    {
        daysTable.deleteRows(at: indexPaths, with: .fade)
    }
    else
    {
        daysTable.insertRows(at: indexPaths, with: .fade)
    }

    self.daysTable.endUpdates()

}

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
{
    return 1
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
    return 40
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{

    if self.barDeals[section].isExpanded == false
    {
        return 0
    }
    return self.barDeals[section].deals.count
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    let cell = tableView.dequeueReusableCell(withIdentifier: "DaysCell", for: indexPath)
    let deals = self.barDeals[indexPath.section].deals[indexPath.row]
    cell.textLabel?.text = deals
    return cell
}


}
  • 1
    You need to save the status of the cell and set it back in the cellForRowAt function. Just add a function "setLookAndFeel(expand:Bool)" in your DaysCell class, If you are not subclassing the UITableViewCell with your custom class now you have a good reason to do it. Base on that parameter the cell should know and expand/collapse itself. – FedeH Dec 20 '18 at 16:15
  • So I am saving the state in a boolean value with barDeals. However ExpandableDeals is a struct with that boolean value. Is there anyway to check if the cell is expanded in cellForRow at then set the boolean based on that? Or is it just easier to to change the struct to subclass UITableViewCell? – Vincent Joseph Dec 20 '18 at 19:06
  • @FedeHenze, sorry forgot to tag you for the above^ – Vincent Joseph Dec 20 '18 at 22:15
  • You could keep your Struct and also subclass the UITableViewCell. Your cell subclass should have a function like initWithDeal( deal: Deal) and base on the deal you set up all your values (cell textLabel for example) inside the cell subclass. – FedeH Dec 21 '18 at 10:04
  • Awesome, I think I understand what you are saying and will give it a try and let you know how it goes. Thanks for your help! @FedeHenze – Vincent Joseph Dec 21 '18 at 14:19

0 Answers0