如何解决等待Completion Handler回调时视图控制器无法释放的问题
iOS URLSession 逃逸闭包导致控制器内存泄漏解决方案
问题核心是@escaping 逃逸闭包强持有视图控制器,形成循环引用,导致控制器无法被正常释放。可通过以下两步组合解决:
在逃逸闭包的捕获列表中添加
[weak self]打破强引用循环
逃逸闭包默认会强持有所有捕获的外部对象,若直接在闭包内部使用self,只要闭包未执行完成,控制器就会被一直持有无法释放。添加[weak self]后,闭包对控制器的引用变为弱引用,不会阻碍控制器的释放。
可在闭包开头先判断self是否存在,若控制器已经销毁直接终止后续逻辑,避免不必要的资源消耗。主动管理未完成的网络请求
仅添加弱引用仅解决了内存泄漏问题,未完成的网络请求依然会在后台执行,浪费流量和系统资源。你可以将发起的URLSessionDataTask存为控制器的私有属性,在控制器deinit方法中主动取消未完成的请求。
完整示例代码
class CustomViewController: UIViewController { // 存储当前正在执行的网络任务 private var currentDataTask: URLSessionDataTask? // 按钮点击触发的加载逻辑 func clickLoadButton() { guard let targetUrl = URL(string: "你的请求地址") else { return } // 发起请求并保存任务实例 currentDataTask = URLSession.shared.dataTask(with: targetUrl) { [weak self] data, response, error in // 控制器已销毁,直接返回不处理后续逻辑 guard let self = self else { return } // 原有业务逻辑处理 if let data = data { DispatchQueue.main.async { // 刷新UI等操作 } } } currentDataTask?.resume() } deinit { // 控制器销毁前主动取消未完成的网络请求 currentDataTask?.cancel() } }
注意:尽量不要使用
[unowned self]替代[weak self],如果闭包执行时控制器已经销毁,unowned引用会触发野指针崩溃,[weak self] + 可选绑定的写法兼容性和安全性更高。
内容的提问来源于stack exchange,提问作者sergey_s
相关产品推荐
相关产品推荐

