Search code examples
iosuitableviewautolayout

iOS table view cell auto height with custom subview


I need pretty simple thing - table cells which automatically detect their own height. There are a lot of examples out there, which basically say "set couple of flags and values on your table and use autolayout in your cell". My case is a bit special - I load the content of the cell from a separate XIB file which is a plain UIView. The first problem comes already when I create that XIB file in interface builder - I don't know how to make it's height to "calculate" according to constraints that I specify. I am always getting IB errors unless I switch to "Freeform" and resize the view to the height matching my constraints. If I don't do that, I will get the following errors:

enter image description here

In the above example I just need a view which height will be 32 (image height) + 2 * 16 (vertical distance constraints of image from parent's top and bottom) plus the margins. Resizing the freeform view in IB until the errors disappear seems like a dirty hack to me, and it is actually not autolayout. As a next step, I define a cell class, where I put this xib view, something like this (sorry for objc code, almost done porting the project to swift):

- (void)awakeFromNib {
    [super awakeFromNib];

    [[NSBundle mainBundle] loadNibNamed:@"CellContent" owner:self options:nil];

    // self.content is an outlet which gets the root of the XIB on load
    [self.contentView addSubview:self.content];

    self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.contentView.leftAnchor constraintEqualToAnchor:self.content.leftAnchor].active = YES;
    [self.contentView.rightAnchor constraintEqualToAnchor:self.content.rightAnchor].active = YES;
    [self.contentView.topAnchor constraintEqualToAnchor:self.content.topAnchor].active = YES;
    [self.contentView.bottomAnchor constraintEqualToAnchor:self.content.bottomAnchor].active = YES;
}

As you might guess, when I run this the cell height is the big freeform one, like in the IB of the content XIB, so no auto layout. It seems like the freeform height is even added as another constraint and there is a constraint conflict which results in some of them being broken at runtime.

Let me know how can I fix this, easily create content views for my cells which have auto heights and which I can embed in my cells to benefit the tableView.rowHeight = UITableViewAutomaticDimension magic?


Solution

  • I found what was my problem. Actually, there were conflicts with constraints added because of autoresizing. So I changed this line (from the question above):

    self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
    

    to:

    self.content.translatesAutoresizingMaskIntoConstraints = NO;
    

    Stupid mistake, the translatesAutoresizingMaskIntoConstraints flag should be disabled for the child view after adding, not for the parent view, as I incorrectly did. After that the magic with cell auto height detection started working like charm.