简体   繁体   English

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

[英]UIGraphicsImageRenderer used in a loop ends with memory issue

I have a simple function like this:我有一个简单的 function 像这样:

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)
}

}

I think it is not complicated as much because I do here a lot of staff with delivered set of images (always 8 images), but when I do it with a loop for i in 1...57 it ends up with memory issue (app is closed after ~31 iterations).我认为这并不复杂,因为我在这里为很多员工提供了一组图像(总是 8 张图像),但是当我for i in 1...57循环时,它最终会出现 memory 问题(应用程序在约 31 次迭代后关闭)。 Why?为什么?

How can I avoid that?我怎样才能避免这种情况? Is there a way to fix that problem?有没有办法解决这个问题?

I suspect the problem you are encountering is caused by accumulating too many temporary ( autorelease ) objects (in this case the CGImage s in the card method) in the loop that is rendering your cards.我怀疑您遇到的问题是由于在渲染卡片的循环中累积了太多临时( autorelease )对象(在本例中为card方法中的CGImage )。

I would try adding an autoreleasepool around the rendering of the card images.我会尝试在卡片图像的渲染周围添加一个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
        }
    }          
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM