UIWebView的整个内容嵌入到UITableView中

11

我已经努力解决这个问题两天了,所以现在我谦卑地向互联网上的智者们求助。

我正在展示一篇文章作为我的UITableView的一部分。为了正确显示,我需要为单元格提供一个高度,我希望它与UIWebView的高度相同,这样我就可以禁用WebView的滚动并将Web内容完整地显示为静态单元格。

我的第一个尝试是在heightForRowAtIndexpath方法中进行呈现,但显然这行不通,因为我需要等待UIWebViewDelegate告诉我WebView何时完全加载并具有高度。过了一会儿,我找到了一个可行的解决方案,它使用Web视图委托在Web视图加载完成时刷新单元格高度。

这很好,直到屏幕大小改变为止。要么是从旋转或全屏我的UISplitView。我在didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation)中强制更新了它,但这会导致它在达到正确高度之前闪烁大约10次。我记录了这个变化,似乎WebView调用自身多次,导致了循环。

日志所示,从我旋转屏幕开始。

它每次重新加载时都会闪烁一次,正如你所看到的,它会重新加载自己多次。

所以,我需要一种方法来在UITableView中显示整个Web视图内容,并在屏幕大小改变时可靠地获取高度。如果有人以前已经成功解决这个问题,请告诉我。如果有人能解决这个问题,我将给予奖励并把我的长子送出去,因为这让我发疯了。

这里是我相关的代码。

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch indexPath.row {
case 4:
        //Content
        print("Height for row called")
        return CGFloat(webViewHeight)
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    switch (indexPath.row){
//HTML Content View
    case 4:
        let cell = tableView.dequeueReusableCellWithIdentifier("ContentCell", forIndexPath: indexPath)
        var contentCell = cell as? ContentCell
        if contentCell == nil {
            contentCell = ContentCell()
        }
        contentCell?.contentWebView.delegate = self
        contentCell?.contentWebView.scrollView.userInteractionEnabled = false
        contentCell?.contentWebView.loadHTMLString((post?.contentHTML)!, baseURL: nil)
        print("Cell For row at indexpath called")
        return contentCell!
}
func webViewDidFinishLoad(webView: UIWebView) {
    updateHeight()
}

func updateHeight(){
    let webView = (self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 4, inSection: 0)) as! ContentCell).contentWebView
    if self.webViewHeight != Double(webView.scrollView.contentSize.height) {
        print("Previous WV Height = \(self.webViewHeight), New WV Height = \(webView.scrollView.contentSize.height)")
        self.webViewHeight = Double(webView.scrollView.contentSize.height)
        tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 4, inSection: 0)], withRowAnimation: .Automatic)
    } else {
        return
    }
}

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
    print("rotated")
        self.updateHeight()
        //tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 4, inSection: 0)], withRowAnimation: .Automatic)
}

我以前遇到过这个问题,由于UIWebViews通常是一个神秘的黑匣子,所以我经常会使用一些解决方法。假设您的文章主要是文本,请考虑通过UITextView原生显示HTML内容,并使用您的HTML作为属性字符串。有关在UITextView中显示HTML的基本示例,请参阅此答案:https://dev59.com/EXE95IYBdhLWcg3wGqIH#20996085。 - Aaron Ash
@AaronAsh 我研究了一下,但似乎带有HTML内容的属性标签对于我的用例来说解析速度太慢了,而且不支持表格。很遗憾... - Oscar Apeland
将它放入tableview单元格中不应该有太大困难,可以看看这里:https://dev59.com/W2Ml5IYBdhLWcg3we283#18818036 。此外,我听说过人们抱怨HTML解析速度慢,但从未在实践中见过。还值得一试吗? - Aaron Ash
看起来应用程序正在对大小的变化进行动画处理,并在动画过程中多次调用updateHeight()函数。在updateHeight()函数中设置一个断点,以查看它是从哪里调用的。我猜你的代码中还有另一个地方也调用了这个函数。 - fishinear
顺便提一下:从您的代码中我了解到,您的表格中只有一个嵌入式tableView单元格?那么我会在VC中处理整个webview逻辑(包括实例化),并在单元格进入屏幕时将webview添加为其子视图(例如使用willDisplayCell)。这样可以避免重新加载所有内容,如果单元格离开屏幕,也不需要等待webview显示。 - amadour
3个回答

1

我通过将行变换动画中的.Automatic更改为.None来解决了这个问题。虽然这仍然不是一个好的解决方案,但至少不再闪烁了。


0
我建议您独立计算网页视图的高度,并将其作为数据的一部分存储,并在heightForRowAtIndexPath调用中使用它返回。这样做更容易,因为您不必在表格视图显示期间计算表格高度。当HTML内容未加载时,请使用标准高度和Web视图的消息。

-1

我认为你的实现没有问题。有几件事情你可以检查一下:

func webViewDidFinishLoad(webView: UIWebView) {
    updateHeight()
    //This function may get called multiple times depending on webpage. 
}

//Use
      self.tableView.beginUpdates()
      self.tableView.endUpdates()
//Instead of
 tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 4, inSection: 0)], withRowAnimation: .None)

    func updateHeight(){
        let webView = (self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 4, inSection: 0)) as! ContentCell).contentWebView
        if self.webViewHeight != Double(webView.scrollView.contentSize.height)
        {
            print("Previous WV Height = \(self.webViewHeight), New WV Height = \(webView.scrollView.contentSize.height)")
            self.webViewHeight = Double(webView.scrollView.contentSize.height)
            self.tableView.beginUpdates()
            self.tableView.endUpdates()
//            tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 4, inSection: 0)], withRowAnimation: .None)
        } else {
            return
        }
    }

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation)
{
    print("rotated")
    let webView = (self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 4, inSection: 0)) as! ContentCell).contentWebView
    webView.reload();
}

在更改屏幕方向时,您需要重新加载 webview。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接