Uitableview Height Does Not Change Dynamically in Swift iOS

Dynamically change UITableViewCell height - Swift 4

You code crashes because of this line

let cell = tableView.cellForRow(at: indexPath) as! AvailableRideCell

From Apple Documentation we know that this method is used for optimization. The whole idea is to get cells heights without wasting time to create the cells itself. So this method called before initializing any cell, and tableView.cellForRow(at: indexPath) returns nil. Because there are no any cells yet. But you're making force unwrapping with as! AvailableRideCell and your code crashed.

So at first, you need to understand, why you should not use any cells inside the cellForRow(at ) method.
After that, you need to change the logic so you could compute content height without calling a cell.

For example, in my projects, I've used this solution

String implementation

extension String {
func height(for width: CGFloat, font: UIFont) -> CGFloat {
let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
let actualSize = self.boundingRect(with: maxSize,
options: [.usesLineFragmentOrigin],
attributes: [NSAttributedStringKey.font: font],
context: nil)
return actualSize.height
}
}

UILabel implementation

extension String {
func height(for width: CGFloat, font: UIFont) -> CGFloat {
let labelFrame = CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude)
let label = UILabel(frame: labelFrame)
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.font = font
label.text = self
label.sizeToFit()
return label.frame.height
}
}

With that, all you need to do is to compute your label and store its font.

var titles = ["dog", "cat", "cow"]

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// number of rows is equal to the count of elements in array
return titles.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cellTitle = titles[indexPath.row]
return cellTitle.height(forWidth: labelWidth, font: labelFont)
}

Dynamic rows height changing

If you'll need to update row height, all you need to do is to call this method when your content had been changed. indexPath is the index path of changed item.

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

Hope it helps you.

Label height in Cell won't change height dynamically

Initially the tableViewCell take the height according to the label's text i.e. Loading...

Once you get Questions response from the Firebase, to reflect the changes in the tableViewCell's content and its height, you need to reload the whole tableView, i.e.

tableView.reloadData()

Call the above code once you receive the API response and after updating the dataSource that you're using for the tableView.

Cannot Set Dynamic TableView Row Height

If you want to set the dynamic tableview row height, you must use autolayout.

Please set the constraint on the UI components in the cell as shown in the image below.

Sample Image

I used UILabel as sample code. For UILabel, be sure to set Lines to 0.

Here is the sample code

class ViewController: UIViewController {

let stringArr = ["Uitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSaa", "Uitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSaaaa", "Uitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOS", "Uitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSaaaaaa", "Uitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSUitableview Height Does Not Change Dynamically in Swift iOSaaaaaa", "bbbb"]

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
super.viewDidLoad()

tableView.dataSource = self

tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableView.automaticDimension
}
}

extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stringArr.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell else {
return UITableViewCell()
}

cell.label.text = stringArr[indexPath.row]

return cell
}
}
  • You need to register the cell in the tableview.

tableView.register(UINib(nibName: “YourCellNibName”, bundle: nil), forCellReuseIdentifier: “YourCellReuseIdentifier”)

uitableview height does not change dynamically in swift ios?

As explanation required to this answer is very detailed.

Follow my other answer "Moving views with constraints" to get idea about how to update layout constraint.

And as per your comment about how to connect NSLayoutConstraint variable with height constraints? as below:

  1. Go to Storyboard.
  2. Select UIView in which you have added constraint. Click on Constraints icon to see all constraints. Right now in below image I have added only one constraint you may find more than that. Check for which constraint you have change it's properties.

Sample Image


  1. Now click on view controller and Click on Show the connection inspector. here you can see all IBOutlets defined in your view controller. As in below image you can see I have created only one IBOutlet for sake of simplicity which is heightConstraint.

Sample Image


  1. And this is how you can add connection to constraint variable.

Sample Image

How to dynamically set tableView height?

Try following :

  1. Declare a variable inside your UIViewController subclass like this.
private var contentSizeObservation: NSKeyValueObservation?

  1. Inside viewDidLoad() or whenever your myTableView is set up, start observing contentSize changes.
contentSizeObservation = myTableView.observe(\.contentSize, options: .new, changeHandler: { [weak self] (tv, _) in
guard let self = self else { return }
self.myTableViewHeightConstraint.constant = tv.contentSize.height
})

  1. Do NOT Forget to clean this up in deinit call -
deinit {
contentSizeObservation?.invalidate()
}

This approach will make sure that your myTableView is always as big in height as it's content.

How to set Dynamically UITableView height in Swift?

Do like this,

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
tblHeightConstraint.constant = downSelectionTbl.contentSize.height
}

Is changing the table height by changing its contrains good practice?

Things I look out for to avoid the problems you are in,

  • Try avoiding any constants or values for dimensions as much as possible.
  • Use constraints and try defining it in exactly one place ( StoryBoard, Xib, or in code).

As its height to be determined by its content attaching to screen edge won't work.

As for your queries,

  • Try checking if any conflicting constraints appear on the storyboard and code. Like if the whole tableview is defined in the storyboard, why not tableView.rowHeight = 50 remains there as well.
  • While deleting, tableView.deleteRows() have .autometic animation. As per doc, case automatic = 100 // available in iOS 5.0. chooses an appropriate animation style for you. Let's set that to .none.

Kindly check if the reviewed snippet below works.

   var data = [1,2,3,4,5,6,7,8,9,10]

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var tableViewHeight: NSLayoutConstraint!

override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = 50
tableViewHeight.constant = CGFloat(data.count) * tableView.rowHeight
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.tableViewHeight.constant = CGFloat(self.data.count) * self.tableView.rowHeight
return data.count
}

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

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
// I think this is causing the problem.
if editingStyle == .delete {
data.remove(at: indexPath.row)
// use no animation
tableView.deleteRows(at: [indexPath], with: .none)
// wont update the constraint here.
// self.tableViewHeight.constant = CGFloat(self.data.count) * self.tableView.rowHeight
}
}

override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(!isEditing, animated: true)
tableView.setEditing(!tableView.isEditing, animated: true)
}
}

Also check these as well if haven't already,

  • Dynamic UITableView height
  • Change UITableView height dynamically


Related Topics



Leave a reply



Submit