问题
I have UIWebView objects into multiples UITableViewCell. Each webView has a different size. Originally, all cells are the same height. Once the user touch the cell, it expand to show all webView Content.
I'm using - (void) webViewDidFinishLoad:(UIWebView *)aWebView to dynamically get the webView height, and - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath to resize the cell. However, webViewDidFinishLoad is only called after the resize method, therefore, the resize is made using old values for webView height.
I tried to call both methods manually in the desired order, but it did worked (I don't think that I should do this at all, anyway...).
Here is my code for load the web view into each cell:
[self.webView setUserInteractionEnabled:NO];
[self.webView loadHTMLString:finalString baseURL:nil];
[cell addSubview:self.webView];
cell.accessoryView = accessoryLabel;
cell.textLabel.text = nil;
self.selectedRowIndex = indexPath.row;
[tableView beginUpdates];
[tableView endUpdates];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
To dynamically get cell size:
- (void) webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
self.cellSize = fittingSize.height;
NSLog(@"Calling webViewDidFinishLoad. Cell size value: %lf", self.cellSize);
}
To change cell size:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath {
if(indexPath.row == self.selectedRowIndex) {
NSLog(@"Resizing cell with size: %lf", self.cellSize);
return self.cellSize + 10;
}
return 44;
}
Here is how the output looks like:
2015-02-24 22:59:08.902 testProject[62200:2703641] Resizing cell with size: 0.000000
2015-02-24 22:59:09.064 testProject[62200:2703641] Calling webViewDidFinishLoad. Cell size value: 501.000000
Is there a way to only resize the cell after webViewDidFinishLoad has been executed?
I really appreciate any help!!
回答1:
I still don't know why this is happing but I solved it using the following approach:
I moved [tableView beginUpdates] and [tableView endUpdates] instructions to webViewDidFinishLoad method. At this way, whenever webViewDidFinishLoad be executed, it will updated the cell size correctly. Although I don't think that is the best solution, it works.
Now, my webViewDidFinishLoad method looks like this:
- (void) webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
self.cellSize = fittingSize.height;
[self.tableView beginUpdates];
[self.tableView endUpdates];
NSLog(@"Calling webViewDidFinishLoad. Cell size value: %lf", self.cellSize);
}
Perhaps the answer helps someone else with similar problems.
回答2:
To prevent infinite loop. the key is if you already got the height of the webview, just return it in webViewDidFinishLoad method. My webViewDidFinishLoad looks like this:
// If the height is already exist, just return to prevent the infinite loop
// The default height is 0.0
if ([[self.webviewHeightDic objectForKey:[NSString stringWithFormat:@"%ld",(long)webView.tag]] floatValue] != 0.0) {
return;
}
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
NSLog(@"Cell height = %f ",fittingSize.height);
// Set the height to the target webview
[self.webviewHeightDic setObject:[NSNumber numberWithFloat:fittingSize.height]
forKey:[NSString stringWithFormat:@"%ld",(long)webView.tag]];
// Refresh the tableView
[self reloadData];
回答3:
I'm curious if it has anything to do with the order in which you do things. Can you try to do this instead:
[cell addSubview:self.webView];
self.webView.frame = ... create frame with cell width and height set to 1 ...
[self.webView loadHTMLString:finalString baseURL:nil];
回答4:
Working solution for me is to use KVO. Take care in removing the observer. Either on didEndDisplayingCell or viewWillDisappear
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.webview.addObserver(self, forKeyPath: "scrollView.contentSize", options: NSKeyValueObservingOptions.New, context: &context)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String: AnyObject]?, context: UnsafeMutablePointer<Void>) {
if let webview = object as? UIWebView {
let cs = webview.scrollView.contentSize
}
}
来源:https://stackoverflow.com/questions/28709899/uiwebview-into-a-uitableviewcell-with-dynamic-size