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

UIImage未释放内存疑似泄漏:保留引用时内存持续增长致崩溃

Vision框架下UIImage引用导致的内存泄漏问题

我最近踩了个大坑,和Vision框架的内存泄漏有关——只要我保留了传入某些Vision相关函数的UIImage参数引用,每次图像操作带来的内存增长就根本不会被释放。要是重复调用这些函数(每次传不同的UIImage实例),内存会一路飙升,最后直接把应用搞崩。

问题复现代码示例

static func memoryNotReleasedExample(image: UIImage) {
    guard let cgImage = image.cgImage else { return }
    let imageTranslationRequest = VNTranslationalImageRegistrationRequest(targetedCGImage: cgImage)
    // 关键问题:如果在这个函数外部或者内部保留了对`image`参数的引用(比如存入类属性)
    // 内存就会持续泄漏,无法被系统回收
    // 后续Vision请求的处理逻辑...
}

问题根源分析

这背后的原因是:Vision框架在处理图像注册请求时,会隐式持有传入的CGImage引用。而UIImage内部管理着CGImage的生命周期,要是我们自己还保留着原始UIImage的引用,就会形成一个“引用链”——系统既无法回收UIImage实例,也无法释放Vision框架持有的CGImage相关内存,最终导致内存持续累积。

解决方案

我试了几个方法,亲测有效:

  • 不要保留原UIImage的引用:在获取到cgImage之后,就让原UIImage实例自然释放,不要把它存在属性或者全局变量里。
  • 直接操作CGImage/Data:如果确实需要缓存图像数据,优先存储CGImage的副本或者图像的Data,而不是整个UIImage实例。
  • 主动清理请求引用:在Vision请求处理完成后,主动将请求对象的targetedCGImage置为nil,帮助系统及时回收内存。

优化后的代码示例

static func memoryFixedExample(image: UIImage) {
    guard let cgImage = image.cgImage else { return }
    // 可以复制一份CGImage,确保原UIImage能被正常释放
    let targetCGImage = cgImage.copy() as! CGImage
    let imageTranslationRequest = VNTranslationalImageRegistrationRequest(targetedCGImage: targetCGImage)
    
    // 执行Vision请求处理逻辑...
    
    // 请求完成后主动清理引用
    imageTranslationRequest.targetedCGImage = nil
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:02:55