循环清除内存

问题描述

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

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,]
    override func viewDidLoad() {
        super.viewDidLoad()
        var result = UIImage.init(color: UIColor.blue,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)
    }
}

带有虚拟图像的阵列和循环。我添加了睡眠,以便在Instruments中看到更好的效果(不睡眠会得到相同的结果)

Memory is growing

如您所见,每秒的存储量正在增加。 有什么办法可以在每个步骤中将内存保持在同一级别? 非常感谢!

解决方法

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

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

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