如何优化在多个TableViewCells中的UIWebView中加载大型和多样化的HTML内容?

时间:2018-08-10 17:33:33

标签: ios swift uitableview uiwebview

我有一个UITableViewCell,里面有一个UIWebView。 我从服务器加载的数据有几个注释,其中包含丰富的HTML内容(文本,图像,链接等)。由于单元格包含UIWebView,因此我必须等到整个内容加载完毕才能获取tableViewCell的高度并进行更新。

我遇到的问题是,当我向下滚动时,单元格将被更新,并且整个视图会出现抖动和闪烁。基本上,我正在寻找一种预加载Web视图的方法以预先获取其高度。而且,这种抽动只会发生在所有单元格都加载了内容之前,因为我是在本地存储每个单元格的高度。

Here's an example of the jittery experience.

cellForRowIndex的代码

open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(indexPath: indexPath) as LiMessageDetailTableViewCell
    cell.delegate = self
    cell.cellModel = LiMessageDetailTableViewCellModel(data: messageObject.originalMessage, index: indexPath)
    cell.heightOfWebView = messageObject.contentHeightsOriginalMessage[indexPath.row]
    if messageObject.contentHeightsOriginalMessage[indexPath.row] != 0.0 {
        cell.updateHeightConstrain()
    }
    return cell
}

TableViewCell中的WebView委托方法

 //MARK:- WEBVIEW DELEGATE
    func webViewDidFinishLoad(_ webView: UIWebView) {
     //This section resizes the webview according to the new content loaded.
        var mframe = webView.frame
        mframe.size.height = 1
        webView.frame = mframe
        let fittingSize = webView.sizeThatFits(.zero)
        mframe.size = fittingSize
        webView.frame = mframe
    /**
    I found that javascript gives a more accurate height when images are
    included since they take more time loading than the normal content and 
    hence sizeThatFits does not always return proper result.
    **/
        let heightInString = webView.stringByEvaluatingJavaScript(from: "document.body.scrollHeight") ?? ""
        guard let heightInFloat = Float(heightInString) else { return }
        guard let index = cellModel?.indexPath else {return}
        constrainHeightOfWebView.constant = fittingSize.height
        guard let cellType = cellModel?.messageType  else { return }
        delegate?.updateHeight(index: index, newHeight: CGFloat(heightInFloat), cellType: cellType)
    }

代表高度的委托方法

func updateHeight(index: IndexPath, newHeight: CGFloat, cellType: LiMessageType) {
    switch cellType {
    case .originalMessage:
        if msgObj.contentHeightsOriginalMessage[index.row] != 0.0 && msgObj.contentHeightsOriginalMessage[index.row] == newHeight {
            return
        }
        msgObj.contentHeightsOriginalMessage[index.row] = newHeight
   .....
    }
    self.tableView.beginUpdates()
    self.tableView.endUpdates()
}

另一个问题是,如果Web视图包含沉重的图像,则每次将单元出队时,整个Web视图都会在重新加载时闪烁,从而导致不良的体验。

Here's the example of webview with image reloading

一段时间后,由于缓存了Webview,图像问题得以解决,但是体验仍然很差。

有没有办法解决这些问题?

1 个答案:

答案 0 :(得分:3)

您可以创建一个Web视图数组并将其存储在视图控制器中,预加载其内容并在加载时显示某种微调器动画。完成所有网络视图的加载后,您应该能够获得各种网络视图的内容高度。

您可能必须修改单元格,以便它们可以接收Web视图作为参数;您将整个网络视图传递到单元格,该单元格将其添加为内容的子视图。

在单元格prepareForReuse()函数中,确保删除所有添加的Web视图。您不希望在重复使用单元格时保留以前的Web视图。