WKWebView 在加载另一个 URL 时不会重新呈现内容

Posted

技术标签:

【中文标题】WKWebView 在加载另一个 URL 时不会重新呈现内容【英文标题】:WKWebView does not re-render content while loading another URL 【发布时间】:2015-05-04 16:06:28 【问题描述】:

我目前正在开发一个使用UIWebView 来显示一些内容的应用程序。它曾经与UIWebView 一起工作得很好,但是当我们将操作系统要求提高到8.1 时,我们决定切换到WKWebView。我们注意到性能有了巨大的提高,但是一些过去可以正常工作的简单想法现在开始失败。经过一些研究,我设法了解发生了什么 - 但我不知道如何解决它。我想知道是否有人可以帮我解决这个问题...

我们的 webview 加载的 URL 需要花费大量时间来完成这项工作,因此在开始请求之前,我们会加载一个静态微调器,这样用户就不会觉得应用程序已经疯了。该静态内容的加载周期已经调整好,因此在正确加载静态内容之前,我们不会启动 URL 请求。只要用户不旋转设备,它就可以正常工作。这是可以看到的:

(出于隐私目的,我不得不更改视图。毕竟我不是此代码的所有者 :-))

我正在使用这个 html 代码来测试大小。 body的背景颜色为深灰色,丑陋的浅灰色框扩大到100%的宽度,减去边距。到现在为止还挺好。但是如果用户旋转设备,就会发生这种情况:

这令人毛骨悚然,因为显然身体的拉伸以匹配最大宽度,但内部 div 处理的相对大小错误。只要请求正在处理,这种情况就会继续。当我强制超时使请求失败时,WKWebView 重新呈现并显示其正确外观:

一旦我发现这一点,我就尝试订阅旋转观察器并通过以下方式强制在 web 视图上重新渲染,但没有成功:

UIWebViewUIScrollView 内部调用viewNeedsDisplay 重新调整UIWebView 的大小 重新定位UIScrollView 内容

所以,到目前为止我的结论:

UIWebView 上没有发生这种情况,只是在新的WKWebView 上发生(我再次测试过,确认) 看起来WKWebView 在处于加载状态时无法正确呈现视图

有人知道是否有办法解决这个问题吗?像我缺少的一个魔法属性,默认情况下是禁用的?我不想认为他们在重新制作 webview 时破坏了这部分...在此先感谢 :)

编辑:自创建帖子以来我尝试过的东西,但没有成功:

通过使用 javascript/本机旋转回调异步更改 DOM 不起作用。在 http 请求结束之前,不会呈现更改。 使用dispatch_async 方法在不同的线程中调用http 请求不起作用。在后台,WKWebview 可能最终使用相同的线程,就像您从主线程调用它一样。

【问题讨论】:

尝试在方向更改时手动刷新页面?我不知道你会使用的确切代码 我做不到。毕竟,如果您没有错过解释中的要点,那么当您期待来自另一个请求的答案时,就会发生此问题,因此,如果我刷新将启动新请求的页面,丢弃旧请求......并且阻止应用程序 ;) 你有没有想过这个问题?我想我在 WKWebview 中运行视频时遇到了类似的问题。 不 :( 仍然没有运气 【参考方案1】:

如果你不介意有点 hacky,有一些方法可以使用 Javascript:

    您可以添加检测更改的 Javascript,例如 window.orientationwindow.onresize。查看是否调用了任何与帧相关的事件。如果它们被调用,只需使用 Javascript 自己调整 div 的大小。

    如果事件从未被触发,您可以使用evaluateJavaScript:completionHandler:自己伪造它们

    您也可以这样制作自己的事件。每当您在应用中检测到设备方向发生变化时,只需发送一个调整 div 大小的脚本即可。

    如果您正在加载 Javascript,您可以查看 <script> 标记的 asyncdefer。这意味着您将不得不更改 web 视图中的代码。

这不是解决此问题的最佳方法,但需要的更改最少。

我还建议您在https://bugreport.apple.com/ 填写错误报告,以便您知道这是否是预期行为。

【讨论】:

我不知道这是否可行,因为我认为这个问题与 UI 线程被传入的 Http 请求阻塞有关。我记得尝试使用 Safari 开发控制台异步修改 DOM,并且在请求完成加载之前它没有开始呈现更改,所以......我不认为添加事件会有所作为。事实上,我不知道我是否能够手动定位该视图,但无论如何我都会尝试 :) 感谢您的洞察力。【参考方案2】:

虽然我没有解决WKWebView 在加载内容时不呈现的解决方案,但我会建议对您的问题采取不同的解决方案。

您可以将加载视图从 web 视图中加载的页面更改为原生 ios 视图。只需在主视图中添加一个子视图,在您开始加载时在 web 视图上方,并在加载完成时将其删除。这可以很好地配合轮换,因此您可以获得与以前相同的体验。

另一个解决方案是在UIWebView 中加载您的加载视图,就像您之前所做的那样,旋转和正常页面在它后面的WKWebView 中正常工作。加载页面时,您也只需隐藏或删除UIWebView

【讨论】:

感谢您的回答。我们考虑过改用原生视图,但由于我们的特殊结构,很难集成到我们的代码中,所以我担心只有在没有其他方法的情况下才会求助于这个...... 我明白了。好吧,您始终可以使用第二种解决方案,添加一个您知道它可以工作的UIWebView 作为子视图,然后在加载完成时将其删除。 是的,我就是这个意思。问题是本机添加/删除 UIWebView 如何影响我们当前的流程:)

以上是关于WKWebView 在加载另一个 URL 时不会重新呈现内容的主要内容,如果未能解决你的问题,请参考以下文章

如果之前已加载某些网页,WKWebView 不会加载 .archive 文件

如何通过 URL 更改而不是页面重定向进行 ajax 加载?

你如何允许 WKWebView 接受重定向 url

如何在 WKWebView 上加载 URL?

WKWebView 不加载第二个 CSS

登录 ios swift 后从 wkwebview 获取令牌