【问题标题】:Deferring viewWillAppear until webViewDidFinishLoad将 viewWillAppear 推迟到 webViewDidFinishLoad
【发布时间】:2009-06-01 03:01:13
【问题描述】:

我有一个在多个视图控制器中使用UIWebViews 的应用程序。 UIWebViews 用于渲染本地生成的html,不需要慢速网络访问。

为了节省内存,我只根据视图控制器viewWillAppear 回调的提示按需加载这些内容。 (并卸载屏幕外实例以响应didReceiveMemoryWarning 消息。)

问题是用户可以看到正在呈现的 html,有时还伴随着样式的闪烁和其他各种令人不快的伪影。我更愿意在屏幕外完成渲染,并在准备好时显示完全渲染的视图。

在 UIWebView 完全呈现之前能够让viewWillAppear 不返回会非常整洁。但是怎么做呢?

我通过发送loadHTMLString:baseURL: 消息告诉UIWebView 要呈现什么。这是异步的,一段时间(很快)之后,webview 的委托被回调webViewDidFinishLoad

我尝试在viewWillAppear 中运行一个runloop,运行NSDefaultRunLoopModeUITrackingRunLoopMode。这在模拟器中有效(它向日志抱怨

[CATransaction 同步] 在事务中调用

但确实有效)但在设备上它会死锁,webViewDidFinishLoad 永远不会被调用。

(另外,UIWebView 加载属性似乎不起作用。至少,在我调用 loadHTMLString:baseURL: 之后,在收到回调之前它不是真的。)

【问题讨论】:

  • “正在加载”属性确实有效,但只有在 UIWebView 出现在屏幕上时才会真正触发加载(如果您跟踪 webViewDidStartLoadwebViewDidFinishLoad)。提示往往会说“将其添加到不透明度为 0.01 的屏幕”,但这对于尚未出现在屏幕上的视图控制器无济于事......

标签: iphone uiwebview


【解决方案1】:

我认为这里有很多解决方案。一个快速的方法是加载 UIWebView,并将其隐藏属性设置为 YES。然后将您的 UIViewController 设置为 UIWebViews 委托并实现:

- (void)webViewDidFinishLoad:(UIWebView *)webView

您将属性设置回 NO。

需要注意的是,如果您有框架/嵌入的内容,webViewDidFinishLoad 将多次触发。因此,您必须对此进行跟踪。如果您正在加载本地内容,这应该不是问题。

【讨论】:

  • 此解决方案让用户在页面绘制到屏幕外时查看空白显示。 (对于我的应用程序,我有一个透明页面将呈现在前面的背景,所以这是值得一看的,但是......)最好为其他显示控制元素(按钮或列表项)的应用程序建模在页面呈现时按下,然后才让完全呈现的视图动画化。
  • 然后让按钮的目标/选择器驱动渲染,并在完成后推进页面(webViewDidFinishLoad: as monowerker 建议)
  • webViewDidFinishLoad: 直到 UIWebView 被移动到屏幕上之后才会被调用......
【解决方案2】:

我最喜欢 monowerker 的解决方案,但另一种解决方案是始终保留已渲染的 UIWebView(在比视图控制器更永久的对象中)。如果 monowerker 的解决方案看起来太具有破坏性,我只会这样做。

【讨论】:

  • UIWebView 会消耗大量内存,当我们收到低内存警告时,它是第一个被扔掉的东西。此外,我的一个用例是渲染从列表视图中选择的对象的细节(例如,在邮件中,您会看到一个消息列表,点击一个并阅读整个内容),所以在我知道要哪个对象之前我无法渲染被查看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 2014-11-20
  • 1970-01-01
  • 2012-05-18
  • 2017-02-01
  • 2021-03-24
相关资源
最近更新 更多