使用后如何释放iOS UIWebView资源

29

我们应用的主屏幕(也就是所有用户都会看到的第一个屏幕)有几个部分,其中大多数包含用户可能想要打开的不同的 Webview。这样做会将内存使用量从仅26MB增加到85MB甚至更多(在打开所有不同的Webview之后)。

我们发现的问题是,一旦关闭它们,所有网页资源似乎都被保留在内存中(使用的内存几乎只减少了几MB)。

我想释放Webview打开时所需的资源,因为后来我们的应用程序有一个非常严格的部分需要大量的内存,如果您之前经过了几个这样的Webview浏览,将完全崩溃应用程序。

我在互联网上找到了几个尝试的选项,但迄今为止没有一个有效。类似以下的东西:

// Try to clean used webview

[self.webView loadHTMLString:@"" baseURL:nil];
[self.webView stopLoading];
self.webView.delegate = nil;
[self.webView removeFromSuperview];
self.webView = nil;

它们对内存使用几乎没有任何影响。这里我是否遗漏了什么?我已经仔细检查了,没有泄漏会使WebView保持打开状态。我也已经释放了我唯一拥有的引用(self.webView = nil;

编辑:我刚刚从头开始创建了一个项目,添加了一个WebView和一个按钮,每次点击它都会加载不同的网页,这反过来又增加了内存使用量。我还添加了一个按钮,当点击时会销毁WebView,猜猜会发生什么?内存保持不变,就像它实际上没有释放任何资源。


你正在使用ARC吗?如果你没有使用ARC,那么你需要在你的web视图上调用release。 - Ankush
@Ankush 是的,我是,不过还是谢谢你。 - h4lc0n
1
也许我误解了您的问题的本质,但我想建议更改控制器架构,只使用一个UIWebView实例,这非常占用资源,但非常具有表现力和自包含性。您可以添加一些服务器代理/聚合器,将所有小部件馈入此Web视图中。稍后,您可以捕获JavaScript事件并应用您的逻辑。 - voromax
@voromax 是的,我也有这个想法。我想创建一个空白项目并使用 webview 进行测试,看看是否可以解决问题。不过,我仍然认为应该有一种方法来清除 webview 使用的任何资源,因为它已经(或应该)不再可用了。感谢您的贡献。 - h4lc0n
3个回答

19

距离我提出这个问题已经过去了几个月,看起来没有人知道任何解决办法,所以我自己回答一下,给那些遇到同样问题的人带来不幸的消息。

我们花了几天时间试图解决这个问题,和一些人交流后,他们暗示我们对此无能为力(它只是一个不同的进程负责处理所有操作,我们无法访问),因此我们决定将WebView访问限制在自定义页面上。

例如,我们有一个新闻栏目打开互联网上的网页。最终我们做的是打开包含标题、正文和与新闻相关的图片的自制网页(仍然增加了资源内存使用,但我们设法将其保持在小容量中,需要打开成千上万条新闻才会有任何危险)。我知道,这不是理想的解决方案。

我仍然希望看到一些建设性的答案,无论是解决方案、变通方法还是任何可以帮助未来遇到同样问题的用户处理问题的想法。


当我在UIWebView中加载许多图像时,我遇到了同样的问题,我进行了搜索但没有找到真正的解决方案。当内容加载到UIWebView中时,它会增加内存并且不会释放直到刷新/重新打开应用程序。 - Hanh Le
我也有这个问题。真的很糟糕,无法解决。我只有一个带视频的 web 视图。我已经尝试了 Stack Overflow 上推荐的所有方法,但内存仍在不断积累。最终,在观看许多视频后,应用程序会崩溃并终止。 :( - BlueVoodoo
你有没有找到更多关于这个问题的信息?我也遇到了完全相同的行为。在查看URL后,内存继续加载,直到最终应用程序崩溃。到目前为止,我已经尝试了网上所有的方法,但我仍然希望有些东西我可能错过了... - George Clingerman
@GeorgeClingerman 很遗憾,目前还没有这种功能...我真心希望苹果有一天能够意识到他们应该让用户释放WebViews的内部资源。 - h4lc0n
2
该死,又撞上这堵墙了。真的,苹果,你是认真的吗? - AlBirdie

7

请阅读 Jason Baker 的这篇文章:

http://www.codercowboy.com/code-uiwebview-memory-leak-prevention/

他创建了一个 类别,可以帮助我们减少 UIWebView 的内存占用。

只需在添加类别后调用两行代码即可。

-(void) dealloc
{

    [self.webview cleanForDealloc];
    self.webview = nil;
    [super dealloc];

}

2
是的,我已经尝试过了。那就是我得到要尝试的选项的地方,但它并没有真正起作用。我会用一个干净的项目再试一次,看看是否有所不同。谢谢。 - h4lc0n

1
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    categoryWebView.stopLoading()
    categoryWebView.removeFromSuperview()
    categoryWebView = nil

    URLCache.shared.removeAllCachedResponses()
    URLCache.shared.diskCapacity = 0
    URLCache.shared.memoryCapacity = 0
    if let cookies = HTTPCookieStorage.shared.cookies {
        for cookie in cookies {
            HTTPCookieStorage.shared.deleteCookie(cookie)
        }
    }
}

没有任何区别。 - Ivan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接