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

Swift 4中URLSession.downloadTask内存循环解决及Web实例未释放排查

排查Web()实例未释放的常见原因

嘿,这个问题我踩过好多次坑了!虽然你的ViewController能正常触发deinit,但Web实例没被释放,90%的概率是循环引用或者未清理的全局持有导致的,咱们一步步捋:

1. Web类内部的闭包循环引用

最常见的情况是Web类里的网络请求(比如URLSession的dataTask)回调中,没有正确处理对self的引用,导致URLSession的任务和Web实例互相强持有,形成循环。

举个错误的示例:

class Web {
    func downloadImage(from url: URL) {
        URLSession.shared.dataTask(with: url) { data, response, error in
            // 这里的self是强引用,URLSession的任务会持有闭包,闭包又持有Web实例
            self.handleDownloadedData(data)
        }.resume()
    }
}

解决办法是在闭包捕获列表里加上[weak self](如果确定Web实例不会提前释放,也可以用[unowned self]):

URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
    guard let self = self else { return } // 可选绑定避免多次写self?
    self.handleDownloadedData(data)
}.resume()

2. ViewController传递给Web的闭包捕获了强引用

虽然你说没给ViewController传强引用,但如果在创建Web实例时,你给它传了一个回调闭包,而闭包里捕获了ViewController的self却没加弱引用,也会导致Web实例被ViewController间接持有(如果Web实例同时持有这个闭包,就会形成循环引用)。

错误写法示例:

// ViewController中的按钮点击方法
@IBAction func downloadButtonTapped(_ sender: UIButton) {
    let web = Web()
    web.downloadImage(from: imageURL) { [self] image in
        // 这里用[self]强引用了ViewController,Web实例持有闭包就会间接持有VC
        self.imageView.image = image
    }
}

修正成弱引用捕获:

web.downloadImage(from: imageURL) { [weak self] image in
    self?.imageView.image = image
}

3. Web实例被全局对象强持有了

如果Web类里做了这些操作,也会导致它无法被释放:

  • 注册了通知但没在deinit中移除观察者
  • 加入了全局的数组、字典等容器
  • 启动了定时器但没停止

比如注册通知的错误写法:

class Web {
    init() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleNotification), name: .someGlobalNotification, object: nil)
    }
}

需要在Web类的deinit中清理:

deinit {
    NotificationCenter.default.removeObserver(self)
    // 如果有定时器,也要在这里调用invalidate()
}

快速排查技巧

你可以给Web类加一个deinit方法,打印日志确认它是否被调用:

class Web {
    deinit {
        print("Web instance deinitialized!")
    }
}

如果这个日志没打印,就对照上面的三点逐一排查,大概率能找到问题~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:37:14