内存泄漏与UIWebView和Javascript
我正在尝试解决一些我的UIWebView
导致的泄漏,无法find它们的原点,也没有解决方法。 我所做的是通过networking请求从networking获取一些内容,然后组装我的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视图,相同的控制器,相同的一切。
仪器显示了一个非常奇怪的模式,其中所有泄漏的对象是各种大小的通用块,并且它们都没有附加任何信息:没有负责任的库,没有负责任的框架等。每次执行loadHTMLString
时, loadHTMLString
添加新的泄漏。
看来有关于UIWebView
泄漏内存的几个线程。 我已经尝试了所有我发现的build议(例如,将NSURLCache
设置为零,或重置它;我试图释放现有的UIWebView,并分配一个新的每次我有新的数据等),但没有任何帮助。
到目前为止,我的调查导致了一个清晰的结果:似乎只有当我加载到视图中的HTML包含一些Javascript时才会出现泄漏。 如果你注意到上面的html
string,它由几个组件组成; 一个是[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>";
所以,这个问题:有没有人知道这里发生了什么? 清楚地包括一个JavaScript文件到我的HTML是使UIWebView
泄漏内存。
事实上,当我重用相同的UIWebView
对象时,或者当我每次有内容时都实例化一个新的对象时,都会出现泄漏,这让我认为javascript文件必须以某种方式处理loadHTMLString
,从而导致泄漏。
有谁知道如何解决这个问题?
我终于发现了一些线索,发生了什么,最重要的是我想分享一个解决方法。
我可以确认,一些JavaScript文件的简单包含导致重新加载的Web视图上的内存泄漏。 我甚至尝试用HTML内容构build文件,然后通过loadRequest
将其加载到UIWebView
,并通过reload
; 泄漏总是在那里。 我会为此发布一个雷达。
什么救了我使用innerHTML
来更新networking视图的内容。 而不是依靠reload
或loadHTMLString
,我用一个空的身体(我的意思是, head
部分在那里,包括所有必需的JS / CSS文件)初始化我的Web视图,然后更新它设置document.body.innerHTML
:
body = [body stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setBody(\"%@\");", body]];
与setBody定义如下:
var setBody = function(body) { document.body.innerHTML = body; }
我获得了两个好处:Web视图更新变得非常快(这是不更新DOM的效果,而另一方面,这并不是完全合乎需要的),并且在Instruments下运行应用程序时没有内存泄漏。 缺点是我不得不微调几个应用程序运行良好的条件; 特别:
-
加载Web视图(即使是一个空的主体页面)也需要花费很多时间,所以你必须同步DOM内容的第一次更新。
-
webViewDidFinishLoading
似乎不可靠:它在document.readyState
变为complete
之前执行; -
document.documentElement.height
,检索页面高度的官方方法似乎也不可靠:解决方法是获取body
部分的“计算样式”并读取其height
值。
希望这可以帮助别人发现他的networking视图正在泄漏内存。