简体   繁体   中英

heightForRowAtIndexPath called before cellForRowAtIndexPath

I am trying to reduce duplicate code when laying out my tableview but running into lifecycle problems. Basically its that heightFroRowAtIndexPath is called before cellForRowAtIndexPath. Which is what should happen and I understand why.

But...

I have a cell that is laid out in a storyboard. It has an optional field. If the optional field is not in the data then I remove a label for that field. However I am removing that label in a custom cell implementation:

CustomCell (extends UITableViewCell)

- (void) configureCellForData: (Data *) data {
    if (data.optional) {
        self.optionalLabel.text = [data.optional];
    } else {
        [self.optionalLabel removeFromSuperview];
    }
}

Then in cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

        CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:self.tableLayout[indexPath.section][indexPath.row]];
        [cell configureCellForData:self.data];
        return cell;
}

Which works great for setting up the cell. However the height is wrong if the optional field is removed, ie I need to adjust if the optional field was removed.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:self.tableLayout[indexPath.section][indexPath.row]];
        CustomCell *headerCell = (CustomCell *) cell;
        if (self.data.optional == nil) {
            return cell.bounds.size.height - headerCell.optionalLabel.bounds.size.height;
        }

        return cell.bounds.size.height;
    } 
}

It does not seem like much but I simplified my check to "data.optional == nil" and it is more complex than that and involves a DB call.

Is there a better way to set this up such that I don't have to make the check twice once when the height for cell is calculated and once when the cell is initialized?

If you wanted to only check once you could store an array of booleans that stores whether or not the data is there or not. So, make the check for each row, store the result into the array, before you make the check next time, check to see if the array has an value for that cell, if it does, use that value, if not, make the database call.

Make sure that you only store values in the array index associated with the indexPath, and if the array is shorter than the indexPath you're at, you know you need to make the call and add the value into the array.

Edit: As I think more about it, I would put the bool value on the cell itself, and then just call cell.isDataAvailable (or whatever you want the value to be) in order to avoid the second call when you go to set the cell up, as you would have already checked this in heightForRowAtIndexPath.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM