2
votes

For dynamic height of my table view cell I take reference from this link. Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

Here is custom cell with all constrains

Here is my code of tableview data source and delegate methods

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
  {
       return arrTemp. count;
  }

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier=@"AutoLAyoutCell";

AutoLayoutTableViewCell *cell=(AutoLayoutTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell==nil) {
    for (id currentObject in [[NSBundle mainBundle] loadNibNamed:@"AutoLayoutTableViewCell" owner:self options:nil]) {
        if ([currentObject isKindOfClass:[UITableViewCell class]]) {
            cell = (AutoLayoutTableViewCell *)currentObject;
            break;
        }
    }
}

cell.IBlblLineNo.text=[NSString stringWithFormat:@"Line:%i",indexPath.row];
cell.IBlblLineText.text=[arrTemp objectAtIndex:indexPath.row];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

CGSize expectedlineLabelSize = [cell.IBlblLineText.text sizeWithFont:cell.IBlblLineText.font constrainedToSize:CGSizeMake(280, 1000) lineBreakMode:NSLineBreakByTruncatingTail];
cell.IBlblLineText.numberOfLines=expectedlineLabelSize.height/17;

CGRect frmlbl=cell.IBlblLineText.frame;
frmlbl.size.height=expectedlineLabelSize.height;
cell.IBlblLineText.frame=frmlbl;

return cell;
}

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

AutoLayoutTableViewCell *cell = (AutoLayoutTableViewCell *)[IBtblAutoLayoutExample cellForRowAtIndexPath:indexPath];

cell.IBlblLineNo.text=[NSString stringWithFormat:@"Line:%i",indexPath.row];
cell.IBlblLineText.text=[arrTemp objectAtIndex:indexPath.row];

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

CGSize expectedlineLabelSize = [cell.lineLabel.text sizeWithFont:cell.lineLabel.font constrainedToSize:CGSizeMake(280, 1000) lineBreakMode:NSLineBreakByWordWrapping];

 cell.IBlblLineText.numberOfLines=expectedlineLabelSize.height/17;
CGRect frmlbl=cell.IBlblLineText.frame;
frmlbl.size.height=expectedlineLabelSize.height;
cell.IBlblLineText.frame=frmlbl;

CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
height += 1.0f;

return height;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
     AutoLayoutTableViewCell *cell = (AutoLayoutTableViewCell *)[IBtblAutoLayoutExample cellForRowAtIndexPath:indexPath];

 CGSize expectedlineLabelSize = [cell.IBlblLineText.text sizeWithFont:cell.IBlblLineText.font constrainedToSize:CGSizeMake(280, 1000) lineBreakMode:NSLineBreakByTruncatingTail];

 return expectedlineLabelSize.height;

}

I have 2 questions :

  1. My issue is I get the error EXE_BAD_EXCESS near the line

    AutoLayoutTableViewCell *cell = (AutoLayoutTableViewCell *)[IBtblAutoLayoutExample cellForRowAtIndexPath:indexPath]; 
    

    in heightForRowAtIndexPath and estimatedHeightForRowAtIndexPath.

  2. Why do I have to write label text in both cellForRowAtIndexPath and heightForRowAtIndexPath?

Also, am I missing anything needed to achieve dynamic height for the cell?

1
Is IBtblAutoLayoutExample the name of your tableview? - E-Riddie
Yes it is IBOutlet to my tableview. - Pooja Shah
I think you don't need to implement heightForRowAtIndexPath and estimatedHeightForRowAtIndexPath, this can be possible with direct constraint in your cell, and you just need to set estimated row and row height property of table view. - Paresh Patel

1 Answers

1
votes

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.