UIGraphicsGetImageFromCurrentImageContext后续帧返回nil无法生成图片如何解决
问题根因及解决方案
核心原因
92帧后生成图片失败的本质是内存/显存溢出触发系统资源限制,代码存在多处资源积压的逻辑漏洞:
- 现有autoreleasepool包裹了整个绘图流程,循环内生成的临时渲染缓存、临时对象无法及时释放,内存持续上涨
- 绘图上下文没有每帧清空,多帧渲染内容持续累积在上下文的显存缓冲区里,占用资源随帧数线性上升
- 所有生成的UIImage全部存储在
images数组中,高清场景下单张图就有数MB甚至数十MB,100帧左右就会触发系统内存上限,直接导致绘图上下文失效 - 循环边界写为
0...count多了一次越界迭代,额外产生无效操作
修正方案
1. 调整autoreleasepool作用范围到循环内部,每帧处理完就释放临时资源
2. 每帧渲染前清空绘图上下文,避免内容累积
3. 不要缓存所有帧到数组,生成一帧就直接传给AssetWriter写入,写完立即释放当前帧
4. 修正循环边界为左闭右开区间
修正后参考代码
// 不需要提前缓存所有image到数组,生成一帧就写一帧 UIGraphicsBeginImageContextWithOptions(settings.size, false, UIScreen.main.scale) guard let context = UIGraphicsGetCurrentContext() else { fatalError("无法获取绘图上下文") } let frameCount = drawAnimationObjectsByIndex.count for index in 0..<frameCount { autoreleasepool { guard let object = drawAnimationObjectsByIndex[index] else { return } // 清空上一帧的上下文内容 CGContextClearRect(context, CGRect(origin: .zero, size: settings.size)) object.parent.render(in: context) guard let image = UIGraphicsGetImageFromCurrentImageContext() else { os_log("第%d帧生成失败,使用上一帧写入", log: self.tag, type: .debug, index) // 这里直接拿上一帧写入AssetWriter,不要缓存到数组 writeLastFrameToAssetWriter() drawAnimationObjectsByIndex[index] = nil return } // 直接写入当前帧到AssetWriter,不要append到images数组 writeFrameToAssetWriter(image: image) drawAnimationObjectsByIndex[index] = nil } } UIGraphicsEndImageContext()
额外优化建议
如果你的视频尺寸大于1080P,可以把UIGraphicsBeginImageContextWithOptions的scale参数改为1,不需要和屏幕scale一致,能大幅降低每帧的内存占用。
内容的提问来源于stack exchange,提问作者Meep
相关产品推荐
相关产品推荐

