IOS: dynamic height with a custom uitableviewcell

I am new at ios development and this is my problem thus far. I am able to dynamically calculate the height of a custom cell via the delegate “heightForRowAtIndexPath”. So on the first load, every thing is display perfectly fine.

My problem is as soon as I start scrolling, everything just messes up. I think that while scrolling the “heightForRowAtIndexPath” is no longer called per cell that get display on screen, so the new cell height cannot be calculated.

  • When I clean Xcode DerivedData I can't run my app in iOS Simulator
  • Connect Two XIBs To One ViewController
  • How to build an iOS framework with weak-linked CocoaPods libraries
  • I have to update frame of everything in storyboard every time I start Xcode
  • In ios6, setting your pageViewController's gestureRecognizers delegate to a viewController causes a crash
  • MKMapView doesn't zoom correctly while user tracking mode is MKUserTrackingModeFollowWithHeading
  • So I’ve been stuck here for a while. I was wondering if any of you could lend me a hand. thank you in advance.

    I’ll post the code to relevant files. These files include the custom cell h and m file. and relevant functions of the view controller m file.

    // ######################################################
    // HelpTableViewCell.h
    #import <UIKit/UIKit.h>
    
    @interface HelpTableViewCell : UITableViewCell  {
      IBOutlet UILabel *labelName;
      IBOutlet UILabel *labelDescription;
    
      IBOutlet UIView *viewBackground;
    }
    
    @property (nonatomic, retain) UILabel *labelName;
    @property (nonatomic, retain) UILabel *labelDescription;
    
    @property (nonatomic, retain) UIView *viewBackground;
    
    @end
    
    // ######################################################
    // HelpTableViewCell.m
    #import "HelpTableViewCell.h"
    
    @implementation HelpTableViewCell
    
    @synthesize labelName;
    @synthesize labelDescription;
    
    @synthesize viewBackground;
    
    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
      self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    
      if (self) {
      }
    
      return self;
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated  {
    
      self.labelName.lineBreakMode = UILineBreakModeWordWrap;
      self.labelName.numberOfLines = 0;
      self.labelName.font = [UIFont boldSystemFontOfSize:15];
      [self.labelName sizeToFit];
    
      self.labelDescription.lineBreakMode = UILineBreakModeWordWrap;
      self.labelDescription.numberOfLines = 0;
      self.labelDescription.font = [UIFont fontWithName:@"Arial" size:15];
      [self.labelDescription sizeToFit];
    
      [super setSelected:selected animated:animated];
    }
    
    - (void) dealloc  {
      [labelName release], labelName = nil;
      [labelDescription release], labelDescription = nil;
    
      [super dealloc];
    }
    
    @end
    
    
    // ######################################################
    // in my view controller m file
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  {  
      static NSString *CellIdentifier = @"HelpTableViewCell";
      HelpTableViewCell *cell = (HelpTableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
      if (cell == nil)  {
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"HelpTableViewCell" owner:nil options:nil];
    
        for (id currentObject in topLevelObjects) {
          if ([currentObject isKindOfClass:[UITableViewCell class]])  {
            cell = (HelpTableViewCell *) currentObject;
            break;
          }
        }
    
      }
    
      cell.labelName.text = [self.instructionName objectAtIndex:indexPath.row];
      cell.labelDescription.text = [self.instructionDescription objectAtIndex:indexPath.row];
    
      return cell;
    }
    
    - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        NSString *cellText = [self.instructionDescription objectAtIndex:indexPath.row];
        UIFont *cellFont = [UIFont fontWithName:@"Arial" size:15];
        CGSize constraintSize = CGSizeMake(320.0f, MAXFLOAT);
        CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
    
        return labelSize.height + 25;  
    }
    

    3 Solutions Collect From Internet About “IOS: dynamic height with a custom uitableviewcell”

    If the text in the cells is going to change, you will need to a call reloadData on your tableView when it does, otherwise the tableView:heightForRowAtIndexPath: won’t be called.

    The way the tableView works is that it gathers the heights for all rows at every reload (and the reload variants). This is how iOS knows the height of the entire table. It doesn’t call tableView:heightForRowAtIndexPath: again when grabbing individual cells. Usually calling reloadData is quite quick and this method, unlike its variants, doesn’t cause any scrolling.

    See stackoverflow question and answer for useful background.

    Problems arise if you have to do a lot of work to calculate heights and you have hundreds or thousands of rows. In one use case I have like this, I cache the row height calculations to get decent performance. But if that’s not your case, just be a little more liberal with reloadData.

    There is a good tutorial that walks you through the process of determining the height that is required to fit your text and sizing the cell height appropriately.

    the tutorial is available here: http://www.raddonline.com/blogs/geek-journal/iphone-sdk-resizing-a-uitableviewcell-to-hold-variable-amounts-of-text/

    I have not attempted the methods in the tutorial myself, but it looks to be pretty thorough.

    Hope this helps!

    Your tableView:heightForRowAtIndexPath: seems correct, but you might want to check the following about the labelDescription cell label in your XIB file:

    • must match the width used in the tableView:heightForRowAtIndexPath: method (in your case, 320)
    • must match the font and size used in the tableView:heightForRowAtIndexPath: method (in your case “Arial” size 15)
    • set the label’s “Adjust to fit” checkbox to NO
    • set the # of lines property to 0 (that way it allows the text to span multiple lines)

    If you suspect the tableView:heightForRowAtIndexPath: method does not get called after you scroll, you can easily verify that by adding a temporary NSLog statement in that method. If it never gets called, you might have forgotten to set your view controller as the UITableView‘s UITableViewDelegate delegate.