How do I change the height of a table cell that has already loaded?

1.7k views Asked by At

Currently I have webviews loading in customized uitableview cells. The problem is the web views have variable sizes. In webViewDidFinishLoad I am able to set the size of the web view based on the actual size of the html document just fine. My problem is the table cells which have already had their height set in heightForRowAtIndexPath before the web views having finished loading. How can I change the height of a table cell after it has already been loaded?

Ideally I feel like I should be able to use some line of code like this.

cellW.frame = cellW.cellWebView.frame;

However I don't seem to have access to cell information in heightForRowAtIndexPath. I've felt like I've explained the situation fairly well, but any code you think I should post I can put up here. I've tried a lot things (so there comments and failed attempts at this everywhere), but the main issue is I can't seem to access cell information in the right places such as heightForRowAtIndexPath. If I could even set cell information somehow in webViewDidFinishLoad, I could simply set the frame of the cell where I am also setting the frame size of the web view.

Below is the setup for my table cell subclass.

#import <UIKit/UIKit.h>
#import "DefinitionsAndConstants.h"

@interface UITableViewCellWebView : UITableViewCell
{
    UIWebView *cellWebView;
}

@property (nonatomic,retain) UIWebView *cellWebView;
@end

Here is what I have tried last trying to use part Gavin's code. But of course there is no way to set the table cell now that I've gotten out because cellForRowAtIndexPath is not assignable.

-(void)webViewDidFinishLoad:(UIWebView *)webViews {
    [webViews stringByEvaluatingJavaScriptFromString:@"twitterfy()"];
    [webViews stringByEvaluatingJavaScriptFromString:@"document.getElementById('tweettext').innerHTML=tweet"];
    NSString* h = [webViews stringByEvaluatingJavaScriptFromString:@"getDocHeightMax()"];
    int height = [h intValue];
    webViews.frame = CGRectMake(0.0f, 0.0f, 320.0f, height);

    NSString* i = [webViews stringByEvaluatingJavaScriptFromString:@"return indexPath"];
    int ii = [i intValue];
    NSIndexPath* ip = [NSIndexPath indexPathForRow:ii inSection:0];

    UITableViewCellWebView *tableCell = (UITableViewCellWebView *)[self.tableView cellForRowAtIndexPath:ip];

    if (tableCell) {
        tableCell.frame = webViews.frame;
    }

    NSLog(@"Got height from webview %d", height);
}
2

There are 2 answers

5
GeneralMike On BEST ANSWER

I would set up a mutable array to read heights from. In viewDidLoad, you'll have to assign some starting values (probably just a bunch of @"44.0", it doesn't really matter, it won't be used for much yet). In your heightForRowAtIndexPath:, just return the number from that array. Then in webViewDidFinishLoad, replace the heights in the array with the height you actually need for that cell (the NSString *h in the code you posted, I believe), and call reloadData on your table view. reloadData will hit heightForRowAtIndexPath:, which will look at the heights array, which now has the actual height needed for that cell, so everything should be shiny.

5
Gavin On

You should be able to do something like this for your heightForRowAtIndexPath method:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCell *tableCell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];

    if (tableCell) {
        return tableCell.cellWebView.frame.size.height;
    }

    return 44;
}

This way, if the table cell is visible, it'll set the height according to the height of the embedded web view, otherwise it'll use a default height. In order to make the table view refresh the height of the cell, you'll have to call the following once the web view is sized properly:

[self.tableView beginUpdates];
[self.tableView endUpdates];

That won't make it reload the cells, which could screw things up for you, it'll just make it check the heights again, and the cell height will animate to the new height.