You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WKWebView触发内存警告致APP终止,如何清理内存避免崩溃?

解决iOS9下WKWebView内存过高导致APP崩溃的问题

我碰到过类似的iOS9环境下WKWebView内存飙升的问题,结合你的描述和代码,帮你梳理下问题根源和可行的解决方案:

为什么你之前的方法没起作用?

  • 你尝试的缓存清理(URLCache和WKWebsiteDataStore)只能清理网页缓存资源,但内存占用飙升的核心原因是WKWebView的独立内容进程中累积了网页的DOM、JS对象、未释放的页面资源(比如视频、iframe),这些内存不在主进程,缓存清理无法直接回收这部分内存。
  • webViewWebContentProcessDidTerminate没被调用,是因为系统内存不足时直接终止了整个APP进程,而非单独终止Web内容进程——只有当Web内容进程自身崩溃(比如JS错误、局部内存溢出)时,这个代理方法才会触发。

有效的解决方案

1. 主动销毁并重建WKWebView(最直接有效)

既然Web内容进程的内存无法通过缓存清理回收,最直接的方式是在收到内存警告时销毁当前WKWebView实例,彻底释放其对应的内容进程内存,之后再重建WebView加载页面:

修改你的代码如下:

import UIKit
import WebKit

class MyAwsomeWebViewController: UIViewController, WKNavigationDelegate {
    var page: WKWebView?
    @IBOutlet weak var WKBaseView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        recreateWebView()
    }

    // 封装WebView创建逻辑
    private func recreateWebView() {
        let config = WKWebViewConfiguration()
        // 为每个新WebView创建独立的进程池,避免共享内存累积
        config.processPool = WKProcessPool()
        
        page = WKWebView(frame: WKBaseView.bounds, configuration: config)
        guard let webView = page else { return }
        
        webView.navigationDelegate = self
        WKBaseView.addSubview(webView)
        // 添加约束确保WebView适配父视图
        webView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            webView.topAnchor.constraint(equalTo: WKBaseView.topAnchor),
            webView.leadingAnchor.constraint(equalTo: WKBaseView.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: WKBaseView.trailingAnchor),
            webView.bottomAnchor.constraint(equalTo: WKBaseView.bottomAnchor)
        ])
        
        // 加载初始页面
        if let url = URL(string: "https://hitta.se") {
            webView.load(URLRequest(url: url))
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        print("**** MEMORY WARNING! ****")
        
        // 1. 销毁当前WebView
        page?.stopLoading()
        page?.navigationDelegate = nil
        page?.removeFromSuperview()
        page = nil
        
        // 2. 清理缓存
        URLCache.shared.removeAllCachedResponses()
        URLCache.shared.diskCapacity = 0
        URLCache.shared.memoryCapacity = 0
        
        // 3. 清理WKWebView相关数据
        DispatchQueue.main.async {
            let dataStore = WKWebsiteDataStore.default()
            dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes()) { records in
                dataStore.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), for: records, completionHandler: {
                    print("All WKWebsiteData cleaned")
                })
            }
        }
        
        // 4. 重建WebView(如果需要立即恢复页面)
        recreateWebView()
    }

    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        print("*** Terminate WebView Process ***")
        // 如果Web内容进程主动崩溃,也可以在这里重建WebView
        recreateWebView()
    }
}

2. 优化页面导航的内存管理

  • 在页面跳转前(比如webView(_:didStartProvisionalNavigation:)),如果是自研网页,可以让网页执行清理逻辑:
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        // 让网页清理全局变量、定时器等资源
        webView.evaluateJavaScript("window.clearAllTimers(); window.clearGlobalVars();") { _, error in
            if let error = error {
                print("JS清理失败: \(error)")
            }
        }
    }
    
  • 对于第三方网页,可以在离开页面时调用webView.stopLoading(),避免后台加载不必要的资源。

3. 避免共享WKProcessPool

如果你的APP中有多个WKWebView,不要共享同一个WKProcessPool实例——共享进程池会让多个Web页面运行在同一个内容进程中,内存会持续累积。为每个WebView创建独立的WKProcessPool,可以让系统更灵活地回收单个内容进程的内存。

额外注意事项

  • iOS9的WKWebView存在一些已知的内存泄漏问题(比如JS交互时的循环引用),检查你的代码中是否存在WKScriptMessageHandler未正确移除、或者闭包持有WebView的情况。
  • 复杂页面(比如包含视频、大量图片)本身内存占用较高,建议在用户离开页面时主动销毁WebView,而不是等到内存警告触发。

内容的提问来源于stack exchange,提问作者Martin Claesson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:44:22