uiwebview的内存问题还是没解决吗?

sunyawang 发布于 2013年12月09日
tinyfool 等1人欣赏。

加载一个优酷首页,30M没了,还没办法释放。。。

共41条回复
adad184 回复于 2013年12月10日

试试

[webView loadHTMLString: @"" baseURL: nil];

在释放之前调用一下

sunyawang 回复于 2013年12月10日

1楼 @adad184 这些方法在stackoverflow都找到过,各种加载空页面,代理置为nil等等都试了,没有用,真是无语啊

adad184 回复于 2013年12月10日

之前做过内嵌web的应用,这个方法还是稍微有点用的,虽然不能完全清理内存,但是不会造成oom

tinyfool 回复于 2013年12月10日

30M没了?然后呢?程序崩溃了?

sunyawang 回复于 2013年12月10日

4楼 @tinyfool 5S上没问题,在iPod touch4上,用一会之后就会收到内存警告,再继续开网页的话就崩溃了。。我的App内嵌了几个视频站点,所以很多操作都是在开网页

sunyawang 回复于 2013年12月10日

it seems like very old and well known problem, people are running into it since 2008 and still no solution(((( discussions.info.apple.com/thread.jspa?threadID=1729697

tinyfool 回复于 2013年12月10日

5楼 @sunyawang 你为什么要嵌入视频网站呢?

sunyawang 回复于 2013年12月10日

7楼 @tinyfool 我把主流的视频网站在我的app里列出来,进入这些视频网页的时候,我可以解析出视频的播放地址,有了这个地址,就可以实现多屏互动的功能,比如通过DLNA协议推送到各种盒子等等。这样就是一个支持多屏互动的简单浏览器了。。

tinyfool 回复于 2013年12月10日

8楼 @sunyawang 大概明白了,我觉得你倒是可以考虑把他们的首页用技术手段分析出来,重构,以适应嵌入设备的内存状况

adad184 回复于 2013年12月10日

或者你考虑用一个全局的webview 每次需要加载网页的时候 就用同一个webview 这样会不会好点

sunyawang 回复于 2013年12月10日

10楼 @adad184 这样不会更好,因为初始化一个webview消耗的内存微乎其微,消耗内存的是load的时候

sunyawang 回复于 2013年12月10日

9楼 @tinyfool 因为怕版权纠纷,所以没敢动他们网页自身的内容,只敢原来什么样就什么样展现出来。。

tinyfool 回复于 2013年12月10日

12楼 @sunyawang 我倒是觉得问题不大吧,因为你最终页面还是他们的吧?

elepone 回复于 2013年12月10日

持续关注这个问题,我也遇到过。@adad184 说的有点用,但确实不是很明显。另外还可以 [NSURLCache setSharedURLCache:sharedCache]; 给个最大数限制,但似乎也不是太起作用。

不知道那些微博类的应用里面大量打开网页是怎么做的?例如随享Pro或者Weico Pro?

sunyawang 回复于 2013年12月10日

14楼 @elepone 这个问题从08年到现在一直没有解决办法。。平时用你说的那些微博应用,是会开一些网页,但是也没有非常频繁,所以没遇到crash的情况

sunyawang 回复于 2013年12月10日

@adad184 简单的测试代码,这样肯定会crash,但是把load去掉的话,仅消耗2M内存

 for (int i = 0; i < 40; i++)
{
    UIWebView *m_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [m_webView setBackgroundColor:[UIColor whiteColor]];
    [self.view addSubview:m_webView];

    [m_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.youku.com"]]];
}
adad184 回复于 2013年12月10日

16楼 @sunyawang 我的意思是 在同一个webview容器中加载多个不同的页面 应该会比 多个webview加载单个页面 好一点

twinsant 回复于 2013年12月16日

30M?这是个很正常的数字。

大约2年前我们写第一版云彩时,就尝试了用WebView做个人空间的实现。

过程中发现2个主要的问题: 1. 浏览器滚动性能极差,相对native滚动,你基本无法忍受那种bianmi的感觉。 2. 内存无法控制释放,我当时用Instruments去调试和观察了所有object的申请和释放,去猜测所有dom树的生成规律。发现找不到可控点来清理内存。最后忍无可忍就做了翻页(webview会在加载新页面时释放上一个页面的内存)

当然,这个可能和我们加载的网页图片多有关(我的页面代码是纯手写纯css渲染的),优酷那种恐龙级别的页面自然会极大地吃掉你的内容。

我挺悲观的,你不要指望在webview这块做太多优化(成本太大)。

少年,接受它吧。

iyu 回复于 2013年12月16日

难道不应该只生成一个UIWebView 然后 load的url变换么。 一次性搞几十个UIWebView一次性加载到view上。 如果真有这样的设计 不应该是先反思自己的么。

tinyfool 回复于 2013年12月16日

19楼 @iyu 那只是测试代码而已,用来测试性能问题的原因的吧

iyu 回复于 2013年12月16日

20楼 @tinyfool 知道是测试代码。 但是是用来解释遇到的问题的。 所以 推测他里面也是这样用的。

tinyfool 回复于 2013年12月16日

21楼 @iyu 这不是废话么,仔细看看他说的意思……你理解完全错了

zhangmeteor 回复于 2013年12月16日

21楼 @iyu 他明显说了,这个影响微乎其微,主要在load上消耗内存啊。。

iyu 回复于 2013年12月16日

22楼 @tinyfool

23楼 @zhangmeteor

呵呵 过来回复是废话。

呵呵 你加一堆空白view 和加一堆有动画的view 资源占用一样? 还是只加一个view 然后 把里面的动画资源替换需要时候替换不同的资源 不用的释放掉要好一些?

我的讨论不是说怎么把webview的30m给降低。 而是说怎么合理的使用webview 而不使得app crash掉。 就算webview本身有问题。

iyu 回复于 2013年12月16日

仔细看了看 10l 就有人说了这个问题了。

tinyfool 回复于 2013年12月16日

25楼 @iyu 他在11楼的回复确实很奇怪……

@sunyawang 你难道是多个webview????

sunyawang 回复于 2013年12月16日

26楼 @tinyfool 我在11楼的回复,是说我2种方式都尝试过,要不然我怎么确定多个webview和单个webview的区别呢,程序里用的方式是单个webview

24楼 @iyu 你的意思我知道,多个webview和单个我都有尝试过,所以得出的结论是内存飙高主要原因不是初始化webview的问题。你说单个webview比多个webview消耗内存更少,这个你说的是正确的。但是相对于webview加载消耗的内存,初始化多个webview消耗的内存微乎其微。 尽管这样,能省则省,所以我代码里一直都是一个webview

sunyawang 回复于 2013年12月16日

24楼 @iyu 另外你呵呵来呵呵去的不太好 大家讨论问题没必要这样 @tinyfool 说你不废话么又不是真的说你说的是废话,顺口一句玩笑,没必要太上心

zhangmeteor 回复于 2013年12月16日

24楼 @iyu 你的讨论木有错,但是楼主的主要矛盾问题明显是webview如何解决。。你告诉他次要矛盾如何解决...

hikui 回复于 2013年12月16日

据传闻UIWebView的内存泄露是WebKit造成的。。

stackoverflow里面确实有一系列的清空。有个总结的帖子可以尝试一下。。。我现在就是这么搞的,不过我们公司的东西webview用得不多,看不出特别大的区别。

tinyfool 回复于 2013年12月16日

28楼 @sunyawang @iyu 我说废话的很大原因是,我基本上无法想像有人可能会一次loading创建一个UIWeview,如果真是那样的话,那我当然就没话说了,我觉得讨论问题最大的障碍就是脑补,中国论坛里面的大多数战争貌似都是因为无穷无尽的脑补。我希望倡导大家尽量不脑补的文化。

iyu 回复于 2013年12月16日

就用了半小时 看了一下lz发的url和在so上看了看 相关内容。

然后写代码测试了一下 自己觉得比较极端的情况了。

代码没有经过严格测试,肯定有很多不合理的地方。

我只是想说明 同一个webview 不停load的话 内存不会出现巨大增加

alt text

这个是在模拟器里面 内存波动在60m 到80m之间 一共加载了40多次。

alt text

这个是在真机iPhone5上 内存波动在40m到50m之间。 也一共加载了40多次。

后面就没有跑了。

我的观点是webview固然有问题。 但是 如果是运用合理的话。 应该不会造成因为内存不断增加而导致app crash这样样子的问题出现。

而且我认为当持有webview的vc被销毁的时候。 我以为webview也会被销毁。 这样持有几十m的内存就得以回收。 这样也不会造成内存不足。 这个观点没有测试

以上, 也许有更加合理的解决方法。 我只是站在一个hello world级别上来想办法解决这个问题。

tinyfool 回复于 2013年12月16日

32楼 @iyu 赞动手精神

sunyawang 回复于 2013年12月16日

32楼 @iyu 同赞!我在5楼也说了,我的5S从来没遇到过crash的情况,在测试手机的iPod touch4上,出现过几次crash

iyu 回复于 2013年12月16日

alt text

33楼 @tinyfool

34楼 @sunyawang

找了台iPod touch4 运行了3分钟的。 iOS 6.1.3

一开始4-5m 然后上升到10m 然后逐渐稳定到7-8m上。 增长幅度很小。 release版本。

adad184 回复于 2013年12月17日

5S 1GB内存 Touch 4 256MB内存

肯定Touch 4容易OOM..

之前做的APP就是结合1楼10楼的方法 减少了内存占用过大而闪退(不能完全的避免,偶尔会有闪退的情况)

当然这主要还是跟机器的内存大小有关

sagacity 回复于 2014年06月28日

参考这篇文章和示例应给能够解决这个问题

http://blog.techno-barje.fr//post/2010/10/04/UIWebView-secrets-part1-memory-leaks-on-xmlhttprequest/

可以在 webViewDidFinishLoad 方法中设置如下:

[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];//自己添加的,原文没有提到。
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"];//自己添加的,原文没有提到。
[[NSUserDefaults standardUserDefaults] synchronize];

关于NSUserDefaults的另类用法还有比如设置UserAgent也可以通过NSUserDefaults来设置。

hanji 回复于 2014年06月29日

37楼 @sagacity 围观迟老师

sagacity 回复于 2014年06月29日

38楼 @hanji 池,谢谢围观

tinyfool 回复于 2014年06月29日

39楼 @sagacity 稀客

sunyawang 回复于 2014年07月01日

40楼 @tinyfool @sagacity

6个月前的帖子了,这种方法没见过,感谢池老师。。

本帖有41个回复,因为您没有注册或者登录本站,所以,只能看到本帖的10条回复。如果想看到全部回复,请注册或者登录本站。

登录 或者 注册
[顶 楼]
|
|
[底 楼]
|
|
[首 页]