循环中使用的UIGraphicsImageRenderer以内存问题结束



我有一个简单的函数,如下所示:

let filteredImages = //array of images
let numbersArray = //array of array of numbers for ex [[1, 2], [2, 3]], total number of elements is 57
for (index, numbers) in numbersArray.enumerated() {

print(">>>>1 INDEX: (index)")
if let cardimage = Box.card(for: filteredImages, numbers: numbers) {
//nothing here for now
}
}
class Box {
class func card(for images: [UIImage], numbers: [Int]) -> CardImage? {
var filteredImages = [UIImage]()
for number in numbers {
guard images.count > number - 1 else {
return nil
}
filteredImages.append(images[number - 1])
}
if filteredImages.count < 8 {
return nil
}
let creator = ImageCreator(radius: 500, backgroundColor: UIColor.athensGray)
return creator.card(from: filteredImages)
}
}
class ImageCreator {
private let radius: CGFloat
private let backgroundColor: UIColor
private let sets: [Set] //Array of predefined objects of my type Set, some numbers like x, y, width, height, radius
init(radius: CGFloat, backgroundColor: UIColor) {
self.radius = radius
self.backgroundColor = backgroundColor
}
func card(from images: [UIImage]) -> CardImage { 
let renderer = UIGraphicsImageRenderer(size: CGSize(width: radius, height: radius))
var coordinates = [ImageCoordinate]()

let image = renderer.image { [weak self] context in
let size = renderer.format.bounds.size
self?.backgroundColor.setFill()
context.cgContext.fillEllipse(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let set = sets.random
for (index, image) in images.enumerated() {
if let positions = set?.positions[index], let cgimage = image.flippedVertically?.cgImage {
context.cgContext.translateBy(x: CGFloat(positions.x), y: CGFloat(positions.y))
context.cgContext.rotate(by: CGFloat(positions.r))
context.cgContext.translateBy(x: CGFloat(-positions.w/2), y: CGFloat(-positions.h/2))
let width = CGFloat(positions.w)
let height = CGFloat(positions.h)
var newWidth: CGFloat = 0
var newHeight: CGFloat = 0
let imageWidth = image.size.width
let imageHeight = image.size.height
let ratio = imageWidth / imageHeight
if ratio > 1 {
newWidth = CGFloat(width)
newHeight = newWidth / imageWidth * imageHeight
} else {
newHeight = CGFloat(height)
newWidth = newHeight / imageHeight * imageWidth
}
context.cgContext.translateBy(x: CGFloat((width - newWidth) / 2), y: CGFloat((height - newHeight) / 2))
context.cgContext.draw(cgimage, in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
context.cgContext.translateBy(x: CGFloat(-(width - newWidth) / 2), y: CGFloat(-(height - newHeight) / 2))
context.cgContext.translateBy(x: CGFloat(positions.w/2), y: CGFloat(positions.h/2))
context.cgContext.rotate(by: CGFloat(-positions.r))
context.cgContext.translateBy(x: CGFloat(-positions.x), y: CGFloat(-positions.y))
coordinates.append(ImageCoordinate(x: positions.x, y: positions.y, w: Double(newWidth), h: Double(newHeight), r: positions.r))
}
}
}
return CardImage(image: image, coordinates: coordinates)
}
}

我认为这并没有那么复杂,因为我在这里为很多员工提供了一组图像(总是8个图像(,但当我使用循环for i in 1...57时,它最终会出现内存问题(应用程序在大约31次迭代后关闭(。为什么?

我该如何避免这种情况?有办法解决这个问题吗?

我怀疑您遇到的问题是由于在渲染卡的循环中累积了太多临时(autorelease(对象(在本例中是card方法中的CGImage(造成的。

我会尝试在卡片图像的渲染周围添加一个autoreleasepool

for (index, numbers) in numbersArray.enumerated() {
autoreleasepool {
print(">>>>1 INDEX: (index)")
if let cardimage = Box.card(for: filteredImages, numbers: numbers) {
//nothing here for now
}
}          
}

最新更新