I have an app that displays a TableView with two relatively static cells at the top, followed by a series of custom cells that contain a label and a segmented control. These cells need to vary in height based on the amount of text in the label.
I'm calculating the required cell height in cellForRowAtIndexPath, storing the value in an array, and then using the values from that array in heightForRowAtIndexPath. It appears, however, that heightForRowAtIndexPath is getting called first, so all of my row heights are 0/nil.
How can I specify the row heights based on the particular content of the cell, when the cell height needs to be known before the cell is configured?
Snippet from cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger currentIndex = indexPath.item;
if (indexPath.item == 0){
static NSString *CellIdentifier = @"MeasurementCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self.cellHeightList insertObject:[NSNumber numberWithInt:44] atIndex:currentIndex];
return cell;
} else if (indexPath.item == 1){
if (self.dataController.isScoreAvailable){
static NSString *CellIdentifier = @"ScoreCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self.cellHeightList insertObject:[NSNumber numberWithInt:46] atIndex:currentIndex];
return cell;
} else {
static NSString *CellIdentifier = @"ScoreCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
[self.cellHeightList insertObject:[NSNumber numberWithInt:0] atIndex:currentIndex];
return cell;
}
} else if (indexPath.item > 1){
NSInteger labelWidth = [UIScreen mainScreen].applicationFrame.size.width - 140; //80 for segment + 3*20 for margins & spacing
CGSize maxSize = CGSizeMake(labelWidth, MAXFLOAT);
CGSize labelSize;
static NSString *CellIdentifier = @"QuestionCell";
InterviewQuestionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
InterviewQuestion *questionAtIndex = [self.dataController objectInListAtIndex:(indexPath.item-2)];
cell.questionLabel.text = questionAtIndex.questionText;
labelSize = [cell.questionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
CGRect labelFrame = CGRectMake(0, 0, labelWidth, labelSize.height);
cell.questionLabel.frame = labelFrame;
cell.questionLabel.numberOfLines = 0;
cell.answerControl.selectedSegmentIndex = questionAtIndex.answer;
cell.answerControl.tag = indexPath.item;
[self.cellHeightList insertObject:[NSNumber numberWithInt:labelSize.height] atIndex:currentIndex];
return cell;
}
return nil;
}
Code from heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger currentIndex = indexPath.item;
return [[self.cellHeightList objectAtIndex:currentIndex] integerValue];
}
Thank You!
First make sure you do not use 'item' on the indexPath, but use 'row'. Item is used I think by UICollectionView, not by UITableView. Second, you need someway to compute the size of a cell without having the cell at hand. Your tableView has a certain width, so based on that you might be able to compute the necessary height. Place this computation in heightForRowAtIndexPath: (if this is intensive, cache it).
Specifically, place the following code not in cellForRowAtIndexPath but in heightForRowAtIndexPath: :
NSInteger labelWidth = [UIScreen mainScreen].applicationFrame.size.width - 140;
CGSize maxSize = CGSizeMake(labelWidth, MAXFLOAT);
CGSize labelSize;
Also, instead of using the UIScreen, simply use the width of the tableView, it makes your code less tightly coupled.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments