5

I tried to use autolayout in custom uitableviewcell And tried to implement the dynamic height according to this SO topic

Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

But my cell is created by xib file. So the method is somewhat different Here is my code in heightForRowAtIndexPath

   -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  {
 myDataItem *item= [[data items] objectAtIndex:[indexPath row]];



   CustomCell *cell = [self.offscreenCells objectForKey:@"CustomCell"];
    if (!cell) {
        cell =  [CustomCell alloc] init];
        [self.offscreenCells setObject:cell forKey:@"CustomCell"];
      }  



    [cell.commentView setText:item.comment]; 
    [cell.displayNameView setText:item.displayNameOfItemOwner];

    [cell.timeAgoView setText:item.timeAgo];
   [cell.imageView setImage:[UIImage imageNamed:@"sis_profile_placeholder"]];


    cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(_prototypeCell.bounds));

    [cell setNeedsLayout];
    [cell layoutIfNeeded];


    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    return height+1; }

And the height that I got from [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] is alway "nil" " When I tried to debug ,I found that all subviews of my customcell are "nil" but the cell itself is not "nil". This might because the customCell of mine is made by nib and when I do [[CustomCell alloc] init] the cell is not fully created.

But I did tried to change method to cell = [_tableView dequeueReusableCellWithIdentifier:@"CustomCell"];

The result is still the same. Every subview is nil . This make the height return to be zero and the make my tableView display incorrectly. Are there any way to solve this ?

I tried to make these upon AutoLayout .Actually, in the previous version ,that I didn't use AutoLayout and calculate the cell height manually .It did work perfectly. Anyway, I just want to tried AutoLayout.

Please help .Thanks in advance

Community
  • 1
  • 1
Kong Hantrakool
  • 1,865
  • 3
  • 20
  • 35
  • 2
    `cell = [CustomCell alloc] init];` won't work if you intend to load the cell from a nib. Take a look at [this question](http://stackoverflow.com/questions/540345/how-do-you-load-custom-uitableviewcells-from-xib-files) for info on how to do this. – smileyborg Mar 24 '14 at 22:30
  • Thank You. I can create the CustomCell from xib now. But the [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] still return nil – Kong Hantrakool Mar 24 '14 at 22:49
  • That method has a return type of CGFloat, not id, so it shouldn't return nil. But if it's returning 0.0, you probably have something wrong with the constraints. Again, my recommendation is to do your constraints in code because it's a lot easier to debug and get right. – smileyborg Mar 25 '14 at 00:16
  • Sorry ,I mean zero. Cell.contentView systemLayoutSizeFittingSize didn't work but when I changed to cell.commentView it did return valid value. Because comment view is only view that has a dynamic height so I used its return value to calculate heightForRow – Kong Hantrakool Mar 25 '14 at 05:18
  • 1
    I am also facing the same issue, did you able to solve this ? – Abhishek Oct 20 '14 at 08:52
  • Yes,see the my answer below – Kong Hantrakool Oct 24 '14 at 16:05

2 Answers2

1

Here is my solution I alloc new cell by NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).

        cell = [topLevelObjects objectAtIndex:0];

  -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath    *)indexPath
 {
 myDataItem *item= [[data items] objectAtIndex:[indexPath row]];



  CustomCell *cell = [self.offscreenCells objectForKey:@"CustomCell"];
if (!cell) {
         NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
 // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).

        cell = [topLevelObjects objectAtIndex:0];

    [self.offscreenCells setObject:cell forKey:@"CustomCell"];
  }  



[cell.commentView setText:item.comment]; 
[cell.displayNameView setText:item.displayNameOfItemOwner];

[cell.timeAgoView setText:item.timeAgo];
  [cell.imageView setImage:[UIImage imageNamed:@"image"]];


cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(_prototypeCell.bounds));

[cell setNeedsLayout];
[cell layoutIfNeeded];


CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height+1; }
Kong Hantrakool
  • 1,865
  • 3
  • 20
  • 35
  • 1
    `return height +1` is for the separator. A more flexible method is `CGFloat separator = ((UITableViewCellSeparatorStyleNone != self.tableView.separatorStyle) ? 1 : 0); return height + separator; }` – SwiftArchitect Jun 16 '15 at 00:34
0

As far as I know, under iOS 8 the proposed solution is not going to work for cells with multiline labels because systemLayoutSizeFittingSize will not take into account the desired cell width (simply put, it will try to layout the label into a single line, thus making the cell wider than it should).

I managed to solve this issue by installing a width constraint in cell's contentView instead of setting the cell bounds. Remember to uninstall such constraint right after calling systemLayoutSizeFittingSize:.

Xavier Jurado
  • 61
  • 1
  • 3