0

In my attempts to use a 100% autolayout driven table view, including the automatic calculation of the cell heights from the instructions at Using Auto Layout in UITableView for dynamic cell layouts & variable row heights, I am seeing some odd behavior when attempting to mix two different cell types in the same table view at the same time.

See these images that show the behavior when I use only cell type 1 or cell type 2, and when I attempt to alternate them within the same table view. Sorry for the non-links, I don't have a high enough reputation to post links yet.

TableCell1:

Image1

TableCell2:

Image2

Both together:

Image3

You can see how in the first 2 images, the cells are showing up with perfect heights calculated so that no extra space is shown above or below any of the UILabel elements. In the third image, I've alternated between cells of type 1 and 2 without making any additional code changes. The heights were perfectly calculated when a single cell identifier was being displayed, even if the text was longer or shorter than the previous cell. I get strange behavior when mixing them.

#import "TableViewController.h"
#import "TableViewCell.h"

@interface TableViewController ()

@end

@implementation TableViewController

- (instancetype)initWithStyle:(UITableViewStyle)style {
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    _lipsumArray = [[NSMutableArray alloc] init];
    for (int i=0; i < 10; i++) {
        [_lipsumArray addObject:[self randomLorem]];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self basicCellAtIndexPath:indexPath];
}

- (TableViewCell *)basicCellAtIndexPath:(NSIndexPath *)indexPath {
    NSString *identifier = ([indexPath row] % 2) ? @"TableCell1" : @"TableCell2";
    TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
    [self configureTableCell:cell atIndexPath:indexPath];
    return cell;
}

- (void)configureTableCell:(TableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    cell.mainText.text = [_lipsumArray objectAtIndex:indexPath.row];
    cell.mainText.font = [UIFont fontWithName:@"Avenir-Medium" size:18.0];

    cell.otherText.text = [self textForOriginalBody:[_lipsumArray objectAtIndex:indexPath.row]];
    cell.otherText.font = [UIFont fontWithName:@"Avenir-Medium" size:14.0];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    static TableViewCell *sizingCell = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *identifier = ([indexPath row] % 2) ? @"TableCell1" : @"TableCell2";
        sizingCell = [self.tableView dequeueReusableCellWithIdentifier:identifier];
    });
    [self configureTableCell:sizingCell atIndexPath:indexPath];

    [sizingCell setNeedsLayout];
    [sizingCell layoutIfNeeded];

    CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height;
}

- (NSString*)randomLorem {
    NSString *loremIpsum = @"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.";
    NSArray *loremArray = [loremIpsum componentsSeparatedByString:@" "];
    int r = arc4random() % [loremArray count];
    r = MAX(3, r); // no less than 3 words
    NSArray *loremRandom = [loremArray objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, r)]];
    return [NSString stringWithFormat:@"%@", [loremRandom componentsJoinedByString:@" "]];
}

- (NSString*)textForOriginalBody:(NSString*)originalBody {
    if (originalBody.length > 80) {
        originalBody = [NSString stringWithFormat:@"%@...", [originalBody substringToIndex:80]];
    }
    return originalBody;
}

@end

What could be causing this type of behavior?

Community
  • 1
  • 1

1 Answers1

0

I know this is an old question, but I was recently having a similar issue with random height issues on uilabels in table cells while using auto layout. I don't know the technical reason why this is happening but a width dependency isn't being met when calculating the height, which is what is causing the weird layout.

To solve this issue I had to subclass my table view cell, and then override the layoutSubviews method and set the preferredMaxLayoutWidth value on each label that was causing me problems to it's own frame width. Here is my swift code that you can convert to Obj-C:

override func layoutSubviews() {

    super.layoutSubviews()
    self.contentView.layoutIfNeeded()
    self.acCaptionLabel.preferredMaxLayoutWidth = self.acCaptionLabel.frame.size.width
    self.acDataDetails.preferredMaxLayoutWidth = self.acDataDetails.frame.size.width
    self.acCommentsLabel.preferredMaxLayoutWidth = self.acCommentsLabel.frame.size.width

}

Hope this helps, let me know if my description is unclear.