循环清除内存

Clear memory on cycle

我有一组图像,需要使用不同的混合选项合并这些图像。我发现,在此过程中,内存不会在循环的每个步骤中释放。即使没有对创建的图像的引用。在此过程中,我的应用程序崩溃了,因为我有很多图像要合并。有什么解决方法或技巧可以在不增加内存的情况下做到这一点吗? 可以使用以下代码重现:

import UIKit
import CoreImage

class ViewController: UIViewController {
    var images =
            [
                UIImage.init(color: UIColor.green, size: CGSize(width: 2048, height: 1152))!,
                UIImage.init(color: UIColor.green, size: CGSize(width: 2048, height: 1152))!,
                UIImage.init(color: UIColor.green, size: CGSize(width: 2048, height: 1152))!,
                UIImage.init(color: UIColor.green, size: CGSize(width: 2048, height: 1152))!,
                UIImage.init(color: UIColor.green, size: CGSize(width: 2048, height: 1152))!,
            ]
    override func viewDidLoad() {
        super.viewDidLoad()
        var result = UIImage.init(color: UIColor.blue, size: CGSize(width: 2048, height: 1152))!
        for image in images {
            //each step reference to previous result released, but memory is growing
            result = merge(result, image)
            sleep(1)
        }
    }

    public func merge(_ back: UIImage, _ top: UIImage) -> UIImage {
        var size = CGSize(width: 2048, height: 1152)
        UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
        let rec = CGRect(x: 0, y: 0, width: 2048, height: 1152)
        back.draw(in: rec)
        //multiply is just for example, it can be different blending option
        top.draw(in: rec, blendMode: .multiply, alpha: 1)
        var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
}

extension UIImage {
    public convenience init?(color: UIColor, size: CGSize) {
        let rect = CGRect(origin: .zero, size: size)
        UIGraphicsBeginImageContextWithOptions(rect.size, true, 0)
        color.setFill()
        UIRectFill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        guard let cgImage = image?.cgImage else {
            return nil
        }
        self.init(cgImage: cgImage, scale: UIScreen.main.scale, orientation: Orientation.up)
    }
}

包含虚拟图像和循环的数组。我添加了 sleep 以便在 Instruments 中更好地查看它(没有 sleep 它具有相同的结果)

如你所见,每一秒内存都在增加。 有什么方法可以使每一步的记忆保持在同一水平? 非常感谢!

您可以将合并包装到 autoreleasepool 范围内:

for image in images {
    autoreleasepool {
        result = merge(result, image)
    }
    sleep(1)
}

UIKit 将它产生的对象添加到 autoreleasepool 中,以便它们在 运行 循环周期结束时被释放。