提问人:harry 提问时间:11/8/2023 更新时间:11/8/2023 访问量:44
在 iOS Swift 应用程序中捕获视频期间创建图像缓冲区时发生内存泄漏
Memory Leak When Creating Image Buffers During Video Capture in iOS Swift App
问:
我正在用 Swift 开发一个 iOS 应用程序,可以捕获旋转视图的视频,但我遇到了内存泄漏问题。导出视频后,内存中仍存储了多余的 2GB,即使在函数完成后也不会释放。尝试在生产环境中第二次运行该函数时,此问题仍然存在,并使应用崩溃。
创建图像缓冲区时似乎会出现此问题。下面是相关的代码片段:
// ViewFrame struct and render method
struct ViewFrame {
private let image: UIImage?
private let snapshot: UIView?
// ... initializers omitted for brevity ...
func render() -> UIImage {
if let existingImage = image {
return existingImage
} else {
return snapshot!.asImage(afterScreenUpdates: true)
}
}
}
// RecordView function within ViewRecordingSession class
private func recordView() {
// ... other code omitted for brevity ...
Timer.scheduledTimer(withTimeInterval: 1 / framesPerSecond, repeats: true) { [weak self] timer in
guard let strongSelf = self else { return }
if !strongSelf.isRecording {
timer.invalidate()
uiView.removeFromSuperview()
} else {
if strongSelf.useSnapshots, let snapshotView = uiView.snapshotView(afterScreenUpdates: false) {
strongSelf.frames.append(ViewFrame(snapshot: snapshotView))
} else {
strongSelf.frames.append(ViewFrame(image: uiView.asImage(afterScreenUpdates: false)))
}
// ... other code omitted for brevity ...
}
}
}
// GenerateAsset function within ViewRecordingSession class
private func generateAsset() {
assetGenerationCancellable?.cancel()
let frameImages = frames.map { $0.render() }
// ... other code omitted for brevity ...
}
使用 Memory Graph Debugger,我发现 CG 栅格数据未解除分配。导致泄漏的特定函数是 UIView.asImage(afterScreenUpdates:)。
内存图指示对捕获的视图或图像的强引用阻止了解除分配。如何确保这些对象在使用后正确释放?
答:
1赞
hogwon choi
11/8/2023
#1
我认为检查一些部分是件好事
1. 检查ViewFrame的快照是否被使用中
例如)
// AS-IS
func render() -> UIImage {
if let existingImage = image {
return existingImage
} else {
return snapshot!.asImage(afterScreenUpdates: true)
}
}
// TO-BE
func render() -> UIImage? {
if let existingImage = image {
return existingImage
} else if let snapshot = snapshot {
let renderedImage = snapshot.asImage(afterScreenUpdates: true)
// If using snapshot before, remove from super view
snapshot.removeFromSuperview()
return renderedImage
}
return nil
}
2. 检查timer.invalidate()
您在 Timer.scheduledTimer 的操作块中使用 [weak self]。但未在 Uur 的代码中调用timer.invalidate()
3. 检查ViewRecordingSession's frames
将 viewFrame 附加到 中后,您可能不会删除 viewFram 中frames
frames
我希望它对你的情况有所帮助。有好的一天~
评论
1赞
harry
11/9/2023
非常感谢,问题是帧未从 viewFrame 中删除
评论