Search code examples
uitableviewnslayoutconstraint

Change UITableViewCell height based on webview content


I have a UIWebView nested within a UITableViewCell.

How can I adjust the cell's height depending on the content I load into the WebView (i.e. after it finishes downloading) ... ?

I have the tableview to set the heightForRowAtPath to be UITableViewAutomaticDimension.

loadContentIntoWebview is called by the owner of the TableView in it's cellForRowAt delegate methods.

I'm noticing heightForRowAt being called before cellForRowAt so my "solution" of setting the height based on the cell's webview's content size won't work.


import UIKit

class MyCell: UITableViewCell, UIWebViewDelegate {

  // MARK: - instance variables

  @IBOutlet weak var myWebview: UIWebView?



  // MARK: - lifecycle methods

  override func awakeFromNib() {
    super.awakeFromNib()

    myWebview?.scrollView.bounces = false;
  }

  override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    // Configure the view for the selected state
  }



  // MARK: - private methods

  func loadContentIntoWebview(htmlString: String) {
    myWebview?.loadHTMLString(htmlString, baseURL: nil)
  }



  // MARK: - UIWebViewDelegate methods

  func webViewDidFinishLoad(_ webView: UIWebView) {
    // dynamically set WebView height
    let tempString = myWebview?.stringByEvaluatingJavaScript(from: "document.body.scrollHeight")
    var tempHeight: CGFloat = 0.0
    if let n = NumberFormatter().number(from: tempString!) {
      tempHeight = CGFloat(n)
    }

    myWebview?.frame.size.height = tempHeight
  }
}

Solution

  • Found a solution ...

    • In webViewDidFinishLoad(_ webView: UIWebView) set the constraint's height as in initial question but use document.body.clientHeight
    • Blast a notification to tell the associated tableview to not reloadData(), but rather beginUpdates() then endUpdates()

    @objc func handleWebviewFinishedLoading() {
        self.webview?.beginUpdates()
        self.webview?.endUpdates()
    }
    

    This seems to redraw the cells without reloading them :)