问题描述
我在 Assets.xcassets 中保存了许多图像。我正在调整它们的大小,使它们更小。后来我不再需要这些图像了。图片没有显示,只是准备好了。因此,获取图像、调整图像大小并保留的类现在已成功取消。
但是 UIGraphicsImageRenderer 调整图像大小后的内存没有释放。内存使用率保持在同一水平。即使我根本没有像下面的示例代码那样使用图像。
我觉得有些不对劲。实际上,我调整图像大小以使用更少的内存,但相反 - 调整大小的图像使用更多内存,并且在取消类所有者后不会释放。
如何释放内存?
Apple 文档说:“...图像渲染器保留 Core Graphics 上下文的缓存,因此重用相同的渲染器比创建新的渲染器更有效。” - 但我不需要它!如何关闭它? 有 28 张图像,这似乎没什么大不了的。但是我有大约 100-300 个图像应该使用 UIGraphicsImageRenderer 调整大小、裁剪和其他操作,在一天结束时使用大约 800-900 Mb 的内存,这些内存只是缓存一些已经完成的渲染工作。
你可以拿下面的代码试试。
class ExampleClass {
func start() {
Worker().doWork()
}
}
class Worker {
deinit {
print("deinit \(Self.self)")
}
func doWork() {
var urls: [String] = []
_ = (1...28).map({ urls.append("pathToTheImages/\($0)") })
// images with resolution 1024.0 x 1366.0 pixels
for url in urls {
let img = UIImage(named: url)! // Memory usage: 11.7 MB
//let cropped = resizedImage(original: img,to: UIScreen.main.bounds.size)
//With this line above - Memory usage: 17.5 MB even after this class has been deinited
}
}
// from 2048 × 3285 pixels >>> to >>> 768.0 x 1024.0 pixels --- for iPad Pro (9.7-inch)
func resizedImage(original: UIImage,to size: CGSize) -> UIImage {
let result = autoreleasepool { () -> UIImage in
let renderer = UIGraphicsImageRenderer(size: size)
let result = renderer.image { (context) in
original.draw(in: CGRect(origin: .zero,size: size))
}
return result
}
return UIImage(cgImage: result.cgImage!,scale: original.scale,orientation: original.imageOrientation)
}
}
解决方法
资产目录不适用于您放置它们的用途。资产目录中图像的目的是直接显示它。如果您有很多图像要加载、调整大小并保存在其他地方而不显示,则需要将它们保留在顶层的应用程序包中,以便您可以调用不缓存图像的 init(contentsOfFile:)
.