why UITableViewAutomaticDimension not working?

IosObjective CSwiftUitableviewRow Height

Ios Problem Overview


Hi there is plenty of question answering the dynamic height for UITableViewCell of UITableView. However I find it weird when I did it.

here's are some of the answer :

here and here

usually this would answer the dynamic height for cell

tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableView.automaticDimension

but in my case I wonder this line wont do anything.

my UITableView is being viewed after clicking tabbar inside the splitview. Is this helpful?

Maybe I'm Missing something. Could anyone help me I spent 2 hours doing silly.

These are my constraint for title the title could be long but the label is not.

enter image description here

and this is my cell

enter image description here

Ios Solutions


Solution 1 - Ios

In order to make UITableViewAutomaticDimension work you have to set all left, right, bottom, and top constraints relative to cell container view. In your case you will need to add the missing bottom space to superview constraint for label under the title

Solution 2 - Ios

I had added constraints programmatically, and accidentally added them to the cell directly, i.e. not on the contentView property. Adding the constraints to contentView resolved it for me!

Solution 3 - Ios

To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout.

  • Assign and implement tableview dataSource and delegate

  • Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight

  • Implement delegate/dataSource methods (i.e. heightForRowAt and return a value UITableViewAutomaticDimension to it)

Objective C:

// in ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

  @property IBOutlet UITableView * table;

@end

// in ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    self.table.dataSource = self;
    self.table.delegate = self;
    
    self.table.rowHeight = UITableViewAutomaticDimension;
    self.table.estimatedRowHeight = UITableViewAutomaticDimension;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return UITableViewAutomaticDimension;
}

Swift:

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

For label instance in UITableviewCell

  • Set number of lines = 0 (& line break mode = truncate tail)
  • Set all constraints (top, bottom, right left) with respect to its superview/ cell container.
  • Optional: Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data.

enter image description here

Note: If you've more than one labels (UIElements) with dynamic length, which should be adjusted according to its content size: Adjust 'Content Hugging and Compression Resistance Priority` for labels which you want to expand/compress with higher priority.

Solution 4 - Ios

Also make sure the Lines for your UILabel in the cell is set to 0. If it is set to 1, it will not grow vertically.

Solution 5 - Ios

I have a specific case, and 99% of the solutions I read didn't work. I thought I'd share my experience. Hope it can helps, as I'd struggled for a couple of hours before fixing this issue.

My scenario:

  • I'm using two TableViews in one ViewController
  • I am loading Custom Cells (xib) in those tableviews
  • Dynamic content in cells consists of two labels
  • Page uses a ScrollView

What I needed to achieve:

  • Dynamic TableView height
  • Dynamic TableViewCells height

What you'll need to check to make it work smoothly:

  • Like every tutorial and answer will tell you, set all the constraints for your label/content (top, bottom, leading & trailing), and set it to the ContentView (Superview). This video tutorial will be helpful.

  • In the viewWillAppear method of my ViewController, I am giving one of my tableViews (tableView2) an estimated row height and then use the UITableViewAutomaticDimension as such (and as seen in all tutorials/answers):

          override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
      
          tableView2.estimatedRowHeight = 80
          tableView2.rowHeight = UITableViewAutomaticDimension
      
      }
    

For me, these previous steps were not enough. My TableView would simply take the estimatedRowHeight and multiply it by the number of cells. Meeeh.

  • As I am using two different tableViews, I created an outlet for each of them, tableView1 and tableView2. Allowing me to resize them in the viewDidLayoutSubviews method. Feel free to ask in comment how I did this.

  • One additional step fixed it for me, by adding this to the viewDidAppear method:

      override func viewDidAppear(_ animated: Bool) {
      tableView1.reloadData() // reloading data for the first tableView serves another purpose, not exactly related to this question.
      tableView2.setNeedsLayout()
      tableView2.layoutIfNeeded()
      tableView2.reloadData()
      }
    

Hope that helps someone!

Solution 6 - Ios

As of iOS 11 and Xcode 9.3, most of the above information is wrong. Apple's Guide suggests setting

    tableView.estimatedRowHeight = 85.0
    tableView.rowHeight = UITableViewAutomaticDimension

WWDC 2017 session 245 (Building Apps with Dynamic Type, about 16:33 into the video) suggests something similar. None of this made a difference for me.

For a Subtitle style cell, all that's necessary to get self-sizing table view cells is to set the number of lines (in the Label section of the attributes inspector) to 0 for both the Title and Subtitle. If one of these labels is too long and you don't set the number of lines to 0, the table view cell won't adjust its size.

Solution 7 - Ios

Forgot to remove tableView(heightForRowAt:indexPath:)

It could be the case that, like me, you accidentally forgot to remove the boilerplate code for the heightForRowAt method.

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 60.0
}

Solution 8 - Ios

For anyone that maybe faced the same problem with me: I struggled for an hour to make it work. A simple UIlabel with top, bottom left and right constraints. I used the willDisplayCell to pass the data to the cell and this was causing problems in cells height. As long as I put that code in cellForRow everything worked just fine. Didn't understand why this happened, maybe the cell height was calculated before willDisplayCell was called so there was no content to make the right calculation. I was just wanted to mention and probably help someone with the same problem.

Solution 9 - Ios

it was working for me fine in iOS 11 and above, while breaking in iOS 10 the solution was to add

table.rowHeight = UITableView.automaticDimension
table.estimatedRowHeight = 200 // a number and not UITableView.automaticDimension

also make sure you add "heightForRowAt" even if it works in iOS 11 and above, its needed if you support iOS 10

   func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }

Solution 10 - Ios

In my case i had two UITableViews, i had to modify this method as

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    CGFloat height = 0.0;
    if (tableView == self.tableviewComments) {
        return UITableViewAutomaticDimension;
    }else if (tableView == self.tableViewFriends) {
        height = 44.0;
    }
    return height;
}

Solution 11 - Ios

Try this, Simple solution it's work for me,

In viewDidLoad write this code,

-(void)viewDidLoad 
{
[super viewDidLoad];
 self.tableView.estimatedRowHeight = 100.0; // for example. Set your average height
 self.tableView.rowHeight = UITableViewAutomaticDimension;
}

In cellForRowAtIndexPath write this code,

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
  static NSString *CellIdentifier = @"Cell";
  UITableViewCell *cell = [tableView 
  dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
  }
    cell.textLabel.numberOfLines = 0; // Set label number of line to 0
    cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"menu"];
    [cell.textLabel sizeToFit]; //set size to fit 
    return cell;
 }

Solution 12 - Ios

For my setup, I first double checked the constraints in the Storyboard for the UITableViewCell were unambiguous top to bottom, and then had to modify code in 2 places.

  1. UITableViewDelegate's tableView(_:heightForRowAt:)

     func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
         return UITableView.automaticDimension
         // return UITableViewAutomaticDimension for older than Swift 4.2
     }
    
  2. UITableViewDelegate's tableView(_:estimatedHeightForRowAt:)

     func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
         return UITableView.automaticDimension
         // return UITableViewAutomaticDimension for older than Swift 4.2
     }
    

Step 1 and 2, lets you to apply autosizing just for particular rows. For applying to the whole UITableView, use:

tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
// return UITableViewAutomaticDimension for older than Swift 4.2

Solution 13 - Ios

In order to make UITableViewAutomaticDimension to work, you need to make sure all 4 corners' constraints is added to the superview. In most case, it works well with UILabel, but sometimes i find UITextView does the trick when UILabel not working well at the time. So try to switch to UITextView and make sure Scrolling Enabled is unchecked in storyboard, or you can also set it programmatically.

Solution 14 - Ios

I had three horizontal items and the most left had a constraint to left, middle one had top, bottom, to the left item and to the right item. The right one had a right, and left to the middle item. The solution was to add additional left and right constraints to the middle item (my label) that were >= some number to the cell.

Solution 15 - Ios

Make sure all views in the cell are constrained to the Content View and not to the cell.

As apple says:

> lay out the table view cell’s content within the cell’s content view. To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge.

Solution 16 - Ios

enter image description hereIn my case I did everything but it did not solve the problem for me, at last, I checked the lines of the label which was fixed to 3. Changing the line value to 0 solves the problem for me. so to tell you all it must be 0 and constraints Top, Bottom, Left, Right must be attached to work fine.

Solution 17 - Ios

An uncommon solution, but one that may save others time: in cellForRowAtIndexPath make sure there is no delay in setting your label text. For some unknown reason, I had it wrapped in a DispatchQueue.main.async block, and this meant that the cell was being returned before the label text was actually set, so the cell and label never expanded to the size of the text.

Solution 18 - Ios

For recent version of ios and swift apple has changed the previously called UITableView.automaticDimension to UITableView().estimatedRowHeight, so to set the row height automatically use it like this: tableView.estimatedRowHeight = 150 //random estimate manually to help the compiler before setting the estimate value. tableView.rowHeight = UITableView().estimatedRowHeight

Solution 19 - Ios

I've got a new solution..that's worked for me.

basically UITableViewAutomaticDimension renamed as UITableView.automaticDimension... I hope..it wo

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCaffeineShotsView Question on Stackoverflow
Solution 1 - IosZell B.View Answer on Stackoverflow
Solution 2 - IosEyeballView Answer on Stackoverflow
Solution 3 - IosKrunalView Answer on Stackoverflow
Solution 4 - IosCamQuestView Answer on Stackoverflow
Solution 5 - IosBptstmlgtView Answer on Stackoverflow
Solution 6 - IosZampanoView Answer on Stackoverflow
Solution 7 - IosGuy DaherView Answer on Stackoverflow
Solution 8 - IosThomasView Answer on Stackoverflow
Solution 9 - IosBassant AshrafView Answer on Stackoverflow
Solution 10 - Iosuser1994956View Answer on Stackoverflow
Solution 11 - IosJaywant KhedkarView Answer on Stackoverflow
Solution 12 - IosPranav KasettiView Answer on Stackoverflow
Solution 13 - IosTerry TanView Answer on Stackoverflow
Solution 14 - IosDarkoView Answer on Stackoverflow
Solution 15 - IosfullmoonView Answer on Stackoverflow
Solution 16 - IosMALIKK HABIB UR REHMANView Answer on Stackoverflow
Solution 17 - IosalstrView Answer on Stackoverflow
Solution 18 - IosNathenael TarekView Answer on Stackoverflow
Solution 19 - IosYeasir Arafat AronnoView Answer on Stackoverflow