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
相关产品推荐
相关产品推荐

