UIWebView和Javascript的内存泄漏

时间:2012-08-05 09:22:28

标签: ios uiwebview memory-leaks

我正在尝试修复我的UIWebView造成的一堆泄漏,无法找到它们的来源或解决方法。我所做的是通过网络请求从网上获取一些内容,然后组装我的HTML并动态加载它:

NSString* body = <some HTML>;
NSString* html = [NSString stringWithFormat:kHTMLTemplate, [self scripts], [self styles], body];
[_webView loadHTMLString:html
               baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];

每次有新内容可用时,我再次执行loadHTMLString以刷新Web视图。我重复使用相同的Web视图,相同的控制器,同样的一切。

仪器显示了一种非常奇怪的模式,其中所有泄漏的对象都是各种大小的通用块,并且 none 它们附有任何信息:没有负责任的库,没有负责任的框架等。执行时间loadHTMLString,添加新的泄漏。

似乎S.O.中有几个主题。约UIWebView泄漏记忆。我已经尝试了我找到的所有建议(例如,将NSURLCache设置为零或重置它;我尝试发布现有的UIWebView并在每次有新数据时分配一个新的等等)但没有任何帮助。

到目前为止,我的调查得出了一个明确的结果:似乎只有在我加载到视图中的HTML包含一些Javascript时才会出现泄漏。如果你注意到上面的html字符串,它由几个组成部分组成;一个是[self scripts],这是一个简单返回的函数:

return @"<script type='text/javascript' src='jquery-1.4.4.min.js'></script>"
        "<script type='text/javascript' src='jmy.js'></script>";

如果我删除它,没有泄漏。但是,只要我向我的HTML添加<script>标记,就会出现泄漏。如果我只是包含jquery文件(或其他任何js文件),它们甚至会出现:

return @"<script type='text/javascript' src='jquery-1.4.4.min.js'></script>";

所以,问题是:有人知道这里发生了什么吗?显然,在我的HTML中包含一个Javascript文件正在使UIWebView泄漏内存。

当我重复使用相同的UIWebView对象或每当我有内容时实例化一个新对象时出现泄漏这一事实让我觉得必须有javascript文件处理方式的东西导致泄密的loadHTMLString

有谁知道如何解决这个问题?

enter image description here

1 个答案:

答案 0 :(得分:11)

我终于找到了一些关于正在发生的事情的线索,最重要的是我想要分享的解决方法。

我可以确认简单包含一些javascript文件导致重新加载Web视图时出现内存泄漏。我甚至尝试使用HTML内容构建文件,然后将其加载到UIWebViewloadRequest,然后通过reload重新加载;泄漏总是在那里。我会为此发布雷达。

救了我的是使用innerHTML更新网页视图的内容。我没有依赖reloadloadHTMLString,而是使用空体初始化我的Web视图(我的意思是head部分,包括所有必需的JS / CSS文件)然后更新它设置document.body.innerHTML

body = [body stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setBody(\"%@\");", body]];

setBody定义如下:

var setBody = function(body) {
    document.body.innerHTML = body;
}

我获得了两个好处:Web视图更新变得非常快(这是不更新DOM的效果,另一方面总体上并不完全可取),并且运行应用程序时没有内存泄漏在仪器下。缺点是我必须微调应用程序正常运行的几个条件;具体是:

  1. 加载网页视图(即使是空的正文页面)需要花费很多,所以你必须将其内容的第一次更新与DOM准备好时同步;

  2. webViewDidFinishLoading似乎不可靠:它在document.readyState成为complete之前执行;

  3. document.documentElement.height,检索页面高度的官方方式似乎也不可靠:解决方法是获取body部分的“计算样式”并阅读其height值。

  4. 希望这可以帮助那些发现他的网络视图泄露内存的人。