设置imageView.image导致内存无限增长的技术问询
UIImageView底层操作导致内存无限增长的原因分析
你的问题核心在于克隆生成的独立UIImage实例+数组强持有+GPU纹理重复创建三者共同作用,导致内存持续飙升,下面拆解UIImageView的底层逻辑和内存增长的根源:
1. UIImageView设置image时的底层核心操作
当你给imageView.image赋值时,底层会执行这些关键操作:
- 强持有UIImage实例:UIImageView会对传入的UIImage保持强引用,直到被新的image替换,或UIImageView本身被释放;
- GPU纹理创建:将UIImage的
CGImage像素数据上传至GPU,生成对应的纹理对象——这部分GPU端内存会被计入XCode的内存统计; - 旧资源异步释放:若之前存在旧的UIImage,UIImageView会释放对它的强引用,但GPU端的旧纹理释放是异步流程,不会立即回收内存。
2. 你的场景内存无限增长的具体原因
结合代码和复现步骤,问题出在以下几点:
- cloneImage生成完全独立的UIImage:通过
cgImage!.copy()创建的全新CGImage,再包装成新UIImage后,完全脱离系统图片缓存(UIImage(named:)的自动缓存机制)的管理,每个UIImage都是独立的内存个体; - 数组长期强持有所有UIImage:
images数组始终持有50个独立的UIImage实例,ARC无法释放这些对象,导致每个UIImage对应的CGImage(CPU端内存)持续占用; - GPU纹理重复累积:滚动列表时,复用的Cell每次设置不同的UIImage,GPU会为每个独立的CGImage创建全新纹理。旧纹理的异步释放速度跟不上新纹理的创建速度,GPU内存持续累积,最终表现为内存无限增长。
3. 解决方法对应的逻辑验证
你提到的三个解决方法正好对应上述问题点:
- 将UIImage置为nil:释放数组对UIImage的强引用,ARC回收UIImage及对应CGImage,GPU纹理也会被异步清理;
- 注释
imageView.image = image:跳过GPU纹理创建和UIImage持有流程,自然不会产生额外内存占用; - 直接使用
UIImage(named:):UIImage(named:)会缓存图片,数组内所有元素都是同一个UIImage实例,GPU仅需创建一次纹理,滚动时复用即可,内存不会增长。
内容的提问来源于stack exchange,提问作者Peter Tao
相关产品推荐
相关产品推荐

