简体   繁体   中英

The correct way to calculate the height of cell

In my app, it have about thousand contents to display in tableView. Each of content has different heights since there are one to three lines UILabel in it. Currently, it calculates and returns the heights of each cell in the tableView delegate function:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

And the way it calculate is:

contentCell = (RSContentViewCell *)self.tmpCell;
UIFont *font = contentCell.myTextLabel.font;
width = contentCell.myTextLabel.frame.size.width + 30;

size = [contentStr sizeWithFont:font
    constrainedToSize:CGSizeMake(width, CGFLOAT_MAX)
    lineBreakMode:contentCell.myTextLabel.lineBreakMode];

height = size.height;
return height;

It works but takes about 0.5 secs to calculate those heights, so the UX is not so good, since the app will be no response during the calculation process. So what's the correct way and where is the correct place to calculate heights of these cell?

UPDATE

The data is from the server and requested at the time that entering the table view.

As you are laoding your Data from a Server you do have a delay no matter what.

=> I suggest you do the Height calculating in background bevor you reload the table / remove the spinner etc.

// Method you call when your data is fetched
- (void)didReciveMyData:(NSArray *)dataArray {
    // start background job
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.myCachedHeightArray = [[NSMutableArray alloc] initWithCapacity:[dataArray count]];
        int i = 0;
        for (id data in dataArray) {
            float height;

            // do height calculation

            self.myCachedHeightArray[i] = [NSNumber numberWithFloat:height];// assign result to height results
            i++;
        }

        // reload your view on mainthread
        dispatch_async(dispatch_get_main_queue(), ^{
            [self doActualReload];
        });
    });
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [[self.myCachedHeightArray objectAtIndex:indexPath.row] floatValue];
}

I put this into my custom cell subclass usually... so the code doesn't clutter my controller and is correct for the cell I use. (+ it is better suited to MVC that way... the height of a cell is a view property IMO)

I DONT measure with each cell, but with a static method - see https://github.com/Daij-Djan/TwitterSearchExampleApp (the ViewController and the DDTweetTableViewCell class for an example)

You still have to do this on the front end but only do it once and cache the results in an Array and use that for future calls.

ie The first time the array value is empty so calculate it and store it in the array.

The next time the array has a value so use that without having to calculate.

How do you set/get self.tmpCell ? Do you save the reusable cell in a property?

Instead getting text from cell and calculating the size you can calculate the size of text from data source of the cell. I mean you set the texts in cellForRowAtIndexPath: somehow (eg. from an array) just use the text from that to calculate it.

For the frame : The cells have the same width of tableview For the font : Just write a method called

- (UIFont *)fontForCellAtIndexPath:(NSIndexPath *)indexpath

and use it also from cellForRowAtIndexPath . It makes your job easier if you change the fonts of texts later.

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