Amit
Amit

Reputation: 4886

UITableview reloadRows not working properly in Swift 3

I have created a UITableView with multiple sections consisting two cells with dynamic cell height. Added a button on second cell. On click of the button increasing the second cell height by changing the constraint height. Action method connected to the button is :

func increaseHeightOnClickOfButton(sender: UIButton) {
    let indexPath = IndexPath(item: 1, section: sender.tag)

    let cell = myTableView.cellForRow(at: indexPath) as! customCell
    cell.viewHeightConstraint.constant = 100

    self.myTableView.reloadRows(at: [indexPath], with: .automatic)
}

Issue: On clicking the button, cell height of second section increases rather than the first one.

I have also tried giving fix value of section like this :

let indexPath = IndexPath(item: 1, section: 0)

but it's not working.

It works only when I try this code:

func increaseHeightOnClickOfButton(sender: UIButton) {
    let indexPath = IndexPath(item: 1, section: sender.tag)

    let cell = myTableView.cellForRow(at: indexPath) as! customCell
    cell.viewHeightConstraint.constant = 100

    self.myTableView.reloadData()
}

But I don't want to reload the whole table view. Can anyone help me what I am doing wrong or is there any other approach to achieve it ?

Edit :

I did one more change, I removed :

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

After clicking the button when I start scrolling the tableview, coming back to the same cell increases it's height. So I guess there is some issue with reloadRows.

Upvotes: 1

Views: 4139

Answers (3)

DonMag
DonMag

Reputation: 77462

Edit:

Modified first post to include a DataSource to track each row's height constraint constant.


Assuming your cell looks something like this:

enter image description here

  • you have added a UIView to the cell (orange view in my example)
  • added a label and button to the UIView
  • set leading, trailing, top and bottom constraints for the view
  • added a Height constraint to the view
  • connected IBOutlets and an IBAction for the button tap inside the cell class
  • set your table class for UITableViewAutomaticDimension

Then this should be a working example. Each time you tap a button, the Height constraint in that cell will be increased by 20-pts. No need to call reload anything...

class TypicalCell: UITableViewCell {

    @IBOutlet weak var theLabel: UILabel!

    @IBOutlet weak var viewHeightConstraint: NSLayoutConstraint!

    var btnAction: (() -> ())?

    @IBAction func didTap(_ sender: Any) {
        btnAction?()
    }

}

class TypicalTableViewController: UITableViewController {

    // 2-D array of Row Heights
    // 4 sections, with 4, 2, 6 and 3 rows
    // all initialized to 40.0
    var rowHeights: [[CGFloat]] = [
        [40.0, 40.0, 40.0, 40.0],
        [40.0, 40.0],
        [40.0, 40.0, 40.0, 40.0, 40.0, 40.0],
        [40.0, 40.0, 40.0]
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 40.0

    }

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return rowHeights[section].count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Typical", for: indexPath) as! TypicalCell

        // Configure the cell...
        cell.theLabel.text = "\(indexPath)"

        // cells are reused, so set the cell's Height constraint every time
        cell.viewHeightConstraint.constant = rowHeights[indexPath.section][indexPath.row]

        // "call back" closure
        cell.btnAction = {
            // increment the value in our DataSource
            self.rowHeights[indexPath.section][indexPath.row] += 20
            // tell tableView it's being updated
            tableView.beginUpdates()
            // set the cell's Height constraint to the incremented value
            cell.viewHeightConstraint.constant = self.rowHeights[indexPath.section][indexPath.row]
            // tell tableView we're done updating - this will trigger an auto-layout pass
            tableView.endUpdates()
        }

        return cell
    }

}

Upvotes: 1

bizkhit
bizkhit

Reputation: 93

You can use the following code to reload cell's height without reloading the whole data:

tableView.beginUpdates()
tableView.endUpdates()

Upvotes: 5

Martin Muldoon
Martin Muldoon

Reputation: 3428

Try reloading the Section:

self.tableView.reloadSections(IndexSet(integer: sender.tag), with: .automatic)

Upvotes: 1

Related Questions