UIWebView和Javascript的内存泄漏

ser*_*gio 10 memory-leaks uiwebview ios

我正在尝试修复一堆泄漏,这些泄漏是我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]]];
Run Code Online (Sandbox Code Playgroud)

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

仪器显示了一个很奇怪的模式中,所有泄漏的对象有各种规格的通用块和没有人连接到它的任何信息:没有一个负责任的图书馆,没有一个负责任的框架等,每一次loadHTMLString执行,新的泄漏被添加.

似乎SO中有几个关于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>";
Run Code Online (Sandbox Code Playgroud)

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

return @"<script type='text/javascript' src='jquery-1.4.4.min.js'></script>";
Run Code Online (Sandbox Code Playgroud)

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

当我重复使用同一个UIWebView对象或每当我有内容时实例化一个新的泄漏时,这个事实让我觉得javascript文件的处理方式必然会loadHTMLString导致泄漏.

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

在此输入图像描述

ser*_*gio 11

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

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

救了我的是innerHTML用来更新网页视图的内容.而不是依赖于reload或者loadHTMLString,我用空体初始化我的Web视图(我的意思是,该head部分在那里,包括所有必需的JS/CSS文件)然后更新它的设置document.body.innerHTML:

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

使用setBody定义如下:

var setBody = function(body) {
    document.body.innerHTML = body;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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