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.
and this is my cell
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
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!
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.
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.
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.
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!
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.
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
}
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.
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
}
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;
}
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;
}
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.
UITableViewDelegate's tableView(_:heightForRowAt:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
// return UITableViewAutomaticDimension for older than Swift 4.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
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.
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.
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.
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.
In 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.
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
I've got a new solution..that's worked for me.
basically UITableViewAutomaticDimension renamed as UITableView.automaticDimension... I hope..it wo
Related
I want to resize custom cell height dynamically.
In my tableView there are three custom columns :
Product Name
Product Qty
Product Price
Now Product Name column does not show full name. Its shows only whatever text fits. But not able to show full name.
Though I've set heightForRowAtIndexPath as follows :
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
This is below lines are set in my CustomCell class
self.productNameLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.productNameLabel.numberOfLines = 0;
Example:
NSString *prodName = #"This is my product name which may contain description with it";
So in above example, my UITableViewCell shows only this much product name: This is my product and it escapes further string.
See below attached property section and constraints...
I want to set product name in Nutrient column
Please help me out, tried every possible solution but not able to resolve this.
This way my uitableview data is showing...but not able to show full name in nutrient.
First of all, estimatedRowHeight should be set to some specific number. It's an estimation that the tableView uses to calculate scroll indicator size, but does not really use it to size cells. So ideally you shoudl set something like:
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
Then make sure that your cells have defined autolayout constraints that can be used to define their size, specifically height. In your case, make sure that the label top anchor is constrained to the cell's contentView.topAnchor, and bottom anchor is constrained to the cell's contentView.bottomAnchor, and leading and trailing of label to leading and trailing of contentView. Thus, when the label has more of the content, it will try to expand, and so should the cell.
Consider using UIStackView to manage cell's content, because then even expanding and collapsing of the cells will easier to manage. If that's your goal, see my answer to another question.
Set these values for your label in Size Inspector(as shown in image) & don't set the height constraint for your label.
You have done good but need some more. First you set.
tableView.estimatedRowHeight = 44
After that bottom constraints which you are given equal to 13 just make it greater than or equal to 13. It will be works for you.
To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout. I just tested following steps and code and works fine.
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
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
}
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
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.
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.
I have a dynamic list of items, each item could have different teamplate/layout (and height). And one those item types could have an internal list of items to select from, regularly 5-6 rows, each has different height.
If I try to describe it further, in my scenario I have one tableview (#slave) inside tableviewcells (#master-cell) of another tableview (#master). Moreover cells (#slave-cell) in my #slave tableview could have different height as well. So I need to layout my #slave to have #master automatically calc and update its size.
I have the issue with the inner table (#slave). In case of auto-layout, to fit all the cell space, the table will be collapsed unlike UILabel or other controls. So what I need here is to get the projected size of #slave table and set the height of the #slave = content height of the #slave.
I found similar post and it works if all rows have the same height but I'm using custom rows with dynamic height so the tableView.contentSize.Height gives me invalid result (basically just multiply rowNumbers * estimatedRowHeight, you can see it on the screenshot, master item #3 has 4 inner cells). Even after calling #slave.reloadData I couldn't get that size.
What is the proper way to build that kind of UI?
Source code with a test project attached (Xamarin.iOS)
I just ran into the same problem a few days ago,and tried to work it around.
The #master-cell works like a childViewController,it's the delegate datasource of the #slave TableViewController.But you cann't have a childViewController in the UITableViewcell.
Customize UITableViewCell to hold necessary property and acts as #slave TableViewController's delegate datasource,and configure #slave-cell's
height and data.
The real problem is the height for #master-cell,
If your data is simple and static,you can compute the height in advance,and return it in method func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat of the ViewController.
Otherwise,add a method to #master-cell which return the height for the whole cell when its property is set.And create a proxy #master-cell to compute the height and return it :
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let cell = CustomUITableViewCell();
let model = self.getModel(indexPath)
cell.model = model
let height = cell.requiredHeight()
return height;
}
It's complex and expensive,but it works.
I think you do not have need of take UITableView inside UITableView. You can take more than one section in UITableView. And use different cellReuseIdentifier. This way your goal will be achieved.
For such a layout ios provide section in tableview, for master items use SectionView(there is delegate method for sectionView -> in which you can provide view for a section) and as different section may have different type of row so make rows according your need and return them according to section.
Perhaps it is because I do not know the background of you project or what you are trying to accomplish, but tableViews inside of tableVIew cells sounds unnecessarily trivial. Rather than using a master tableView with #slave tableViews, it would be cleaner to just break things out by section in a single tableView as stated in a previous answer. There are UITableViewDelegate methods designed to streamline this for you!
first you have to get string's height then the height have to give in below tableView delegate
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return stringHeight;
}
it is working for me.
I'm using Xcode 8.3.2 and Swift3.1.
I had the same requirement, have tried all, nothing worked for me.
Finally, UIStackView is what worked for me.
In a tableviewcell, I have added a UIStackView(Verticle), keep adding sub cells to that UIStackView. And it automatically increased the cell height.
Check the following to add UIStackView programmatically.
Add views in UIStackView programmatically
If you Use Different Sections and Rows use the below format, its working for me,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
return 121;
}
if(indexPath.section==1)
{
return 81;
}
if (indexPath.section%2 == 0 && indexPath.row == 1) {
return 161;
}
if (indexPath.section%2 != 0 && indexPath.row == 0) {
return 81;
}
if (indexPath.section==16 && indexPath.row==0) {
return 161;
}
else
{
return 44;
}
}
i have Template code, different section and row, its each row have different sizes, so i have give this type of code, if you get idea see the above code then its helpful for you,
or
If you change the height for Content text size use the below code, its calculate the content size then change the height(UILabel) size, its working for me
-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
ListModel *model = [ListArray objectAtIndex:indexPath.row];
CGRect labelRect = [model.content boundingRectWithSize:CGSizeMake(tableView.frame.size.width - 90 - 15, 0)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{
NSFontAttributeName : [UIFont fontWithName:#"Arial" size:14.0]
}
context:nil];
CGFloat heightOfCell = labelRect.size.height + 60;
if(heightOfCell > 106)
return heightOfCell;
return 106;
}
hope its helpful
yes of course you can have as many prototypes cells as you want for example check this piece of code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("TodayWeatherCell", forIndexPath: indexPath) as! SITodayWeatherTableViewCell
cell.setupCell(upCommingWeather)
cell.aboutCityUpdateTableViewClousure = {
self.tableView.reloadData()
}
return cell
}else {
let cell = tableView.dequeueReusableCellWithIdentifier("cityDetailCell", forIndexPath: indexPath) as! SICityDetailTableViewCell
let detail = detailCity[indexPath.row]
cell.setupCityDetail(detail)
return cell
// Configure the cell...
}
}
There are two different cells in one single UITableView.
Hope it helps.
I have problem with UILabel in UITableView. I want to bring film's plot in UILabel, but when application started, I have just one line of non-full plot, but when I scroll down and up, I get full film's plot with 2-3 lines. What problem can be?
In UILabel preferences I choose 0 lines (It makes label is multiline).
In ViewController, in "viewDidLoad" I wrote two line of code, to make cell resizable:
self.searchTableView.estimatedRowHeight = 44.0
self.searchTableView.rowHeight = UITableViewAutomaticDimension
Call [view layoutIfNeeded] after set the text of UILabel. It will layout subviews again.
With UILabel over multiple lines, you have to give it a hand to know when to wrap text during layout.
To do this you need to set the preferredMaxLayoutWidth property. See https://developer.apple.com/library/ios/documentation/UIKit/Reference/UILabel_Class/#//apple_ref/occ/instp/UILabel/preferredMaxLayoutWidth
So in your cellForRowAtIndexPath method add something like:
cell.yourUILabelIBOutlet.preferredMaxLayoutWidth = tableView.frame.size.width;
You can do this using autolayout in UITableViewCell. it's working for me.
Add UILabel in your tableview
Set UILabel Leading,Trailling,top and bottom constraints.(Note : don't set height for that label)
Then set UILabel NO.Of line 0 and set Line Break mode.
Set your tableview cell height
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
tableView.estimatedRowHeight = 150
return UITableViewAutomaticDimension
}
Add the below code and try it. It works##
-(void)viewDidLoad {
[super viewDidLoad];
//at last line of viewDidLoad
[self performSelector:#selector(reloadtable) withObject:nil afterDelay:1.0];
}
-(void)reloadtable
{
[self.tableView reloadData];
}
So I want to make timeline content like instagram, I'm using custom cell on my uitableview. My problem is I already set the cell height to 345 on the storyboard but I get cell table like below:
and here is my custom cell on storyboard:
How can I fix it, so I can get the result like on my storyboard?
The reason that you are having this issue is you have probably set your Custom tableview cell's row height to 345 but that is not set as custom while your UITableview's row height is less than 345. So, what you need to do is go to storyboard and select the Table(UITableview) and set its row height to the maximum possible row height.
Let's assume that you are going to have two different kind of row heights. One with 345 and another with 325. As 325<345, you set your tableview's row height to 345.
Now, select the custom tableview cell and make its row height as custom and set that to either 345 or 325. In your case, it will be 345.
It should be good now.
However, more appropriate way when you have different cell size would be to use the delegate method for row height specification.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row==0){
return 345;
}
else if(indexPath.row==1){
return 325;
}
else{
return 300; //a default size if the cell index path is anything other than the 1st or second row.
}
}
Use this delegate method:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 345
}
In your UITableViewController subclass, set self.tableView.rowHeight = 345. Might be a bug with storyboard heights not being translated.
You can set Table View Cell height here.
I'm working on an app where I face a strange issue. I've created a UITableViewController in the storyboard and added a prototype cell. In this cell, I've added an UILabel element and this UILabel takes up the whole cell. I've set it up with Auto Layout and added left, right, top and bottom constraints. The UILabel contains some text.
Now in my code, I initialize the the rowHeight and estimatedRowHeight of the table view:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 50
}
And I create the cell as follows:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("HelpCell") as? UITableViewCell
if(cell == nil) {
cell = UITableViewCell(style: .Default, reuseIdentifier: "HelpCell")
}
return cell!
}
I return two rows in my table view. Here comes my problem: the height of the first row is way to large. It appear that the second, third row etc all have a correct height. I really don't understand why this is the case. Can someone help me with this?
I had a problem where the cells' height were not correct on the first load, but after scrolling up-and-down the cells' height were fixed.
I tried all of the different 'fixes' for this problem and then eventually found that calling these functions after initially calling self.tableView.reloadData.
self.tableView.reloadData()
// Bug in 8.0+ where need to call the following three methods in order to get the tableView to correctly size the tableViewCells on the initial load.
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
self.tableView.reloadData()
Only do these extra layout calls after the initial load.
I found this very helpful information here: https://github.com/smileyborg/TableViewCellWithAutoLayoutiOS8/issues/10
Update:
Sometimes you might have to also completely configure your cell in heightForRowAtIndexPath and then return the calculated cell height. Check out this link for a good example of that, http://www.raywenderlich.com/73602/dynamic-table-view-cell-height-auto-layout , specifically the part on heightForRowAtIndexPath.
Update 2: I've also found it VERY beneficial to override estimatedHeightForRowAtIndexPath and supply somewhat accurate row height estimates. This is very helpful if you have a UITableView with cells that can be all kinds of different heights.
Here's a contrived sample implementation of estimatedHeightForRowAtIndexPath:
public override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCell
switch cell.type {
case .Small:
return kSmallHeight
case .Medium:
return kMediumHeight
case .Large:
return kLargeHeight
default:
break
}
return UITableViewAutomaticDimension
}
Update 3: UITableViewAutomaticDimension has been fixed for iOS 9 (woo-hoo!). So you're cells should automatically size themselves without having to calculate the cells height manually.
As the Apple says in the description of setNeedsLayout:
This method does not force an immediate update, but instead waits for the next update cycle, you can use it to invalidate the layout of multiple views before any of those views are updated. This behavior allows you to consolidate all of your layout updates to one update cycle, which is usually better for performance.
Because of this you should add needed lines of code (which should be executed with right layout) in dispatch_after block(which will put your method in queue of RunLoop). And your code will be executed after needs layout applies.
Example:
- (void)someMethod {
[self.tableView reloadData];
[self.tableView setNeedsLayout];
[self.tableView layoutIfNeeded];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//code which should be executed with the right size of table
});
In iOS 8, assigning the estimatedRowHeight a value turns on the new iOS 8 automatic row height calculation feature. This means that the cell's height is derived by using its internal constraints from the inside out. If there's something wrong with those constraints you'll get odd results. So there's something wrong with your cell constraints. They are probably ambiguous; that is the usual reason for inconsistency. However that's all I can tell you, since you have not actually shown / described the constraints.
I suggest removing the bottom constraint on the UILabel. It will resize according to the text and the cell should resize as well.
If that didn't resolve the issue, try adding the following in viewDidLoad() :
self.tableView.reloadData()
This worked for me
- (void)layoutSubviews
{
[super layoutSubviews];
// Your implementation
}
I got this from here >> http://askstop.com/questions/2572338/uitableview-displays-separator-at-wrong-position-in-ios8-for-some-cells