在 iOS Swift 应用程序中视频捕获期间创建图像缓冲区时出现内存泄漏

问题描述 投票:0回答:1

我正在用 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 ...
}

使用内存图形调试器,我发现 CG 栅格数据没有被释放。导致泄漏的具体函数是 UIView.asImage(afterScreenUpdates:)。

内存图表明对捕获的视图或图像的强引用正在阻止释放。如何保证这些对象使用后正确释放?

ios swift memory-leaks avfoundation core-graphics
1个回答
0
投票

我认为检查一些部分是很好的

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]。但是

timer.invalidate()
在你的代码中没有被调用

3.检查
ViewRecordingSession's frames

frames
中添加viewFrame后,您可能无法在
frames

中删除viewFram

希望对您的情况有所帮助。祝你有美好的一天~

© www.soinside.com 2019 - 2024. All rights reserved.