Swift 5 MacOS Image Resizer 内存问题

Swift5 MacOS ImageResize memory issue

我是 Mac OS 应用程序开发的新手 Swift。但我尝试制作简单的 ImageResizer 应用程序。我必须调整 50k 图片的大小。 10个小时后,内存增加到近120GB。我以为 Swift 也有垃圾收集器。为什么会增加内存?我会告诉你我的代码。

for i in 0..<paths.count {
    let path = paths[i]

    if let image = NSImage(contentsOf: path) {
        ...

        if self.resize(image: image, size: size, to: URL(fileURLWithPath: resizedImagePath)) {
            print("Image saved to \(resizedImagePath)")
            continue
        }
    }
}

func resize(image: NSImage, size: Int, to url: URL) -> Bool {
    if !image.isValid {
        print("invalid image")
        return false
    }

    guard let pixelsWide = image.representations.first?.pixelsWide else {
        return false
    }

    let factor: CGFloat = CGFloat(pixelsWide) / image.size.width

    var width: CGFloat = CGFloat(size)
    var height: CGFloat = CGFloat(size)
    if image.size.width > image.size.height {
        height = width * image.size.height / image.size.width
    } else {
        width = height * image.size.width / image.size.height
    }

    let rep = NSBitmapImageRep(bitmapDataPlanes: nil,
                               pixelsWide: Int(width),
                               pixelsHigh: Int(height),
                               bitsPerSample: 8,
                               samplesPerPixel: 4,
                               hasAlpha: true,
                               isPlanar: false,
                               colorSpaceName: .deviceRGB,
                               bytesPerRow: Int(width * 4),
                               bitsPerPixel: 32)
    rep?.size = NSSize(width: width / factor, height: height / factor)

    let ctx = NSGraphicsContext(bitmapImageRep: rep!)
    NSGraphicsContext.saveGraphicsState()
    NSGraphicsContext.current = ctx
    image.draw(in: NSMakeRect(0, 0, width / factor, height / factor))
    ctx?.flushGraphics()
    NSGraphicsContext.restoreGraphicsState()

    // Get NSData, and save it
    let data = rep?.representation(using: .png, properties: [:]) // properties as! [String : Any]) //
    do {
        try data?.write(to: url)
        return true
    }
    catch {
        return false
    }
}

Swift 使用 ARC(自动引用计数),这意味着当对该对象的强引用数达到零时,该对象将被释放。我没有立即在提供的代码中看到问题出在哪里,但我怀疑代码中的其他地方一定有某个位置,您持有对图像的引用。

您可以将循环中的整个代码放在 autoreleasepool:

If you write a loop that creates many temporary objects. You may use an autorelease pool block inside the loop to dispose of those objects before the next iteration. Using an autorelease pool block in the loop helps to reduce the maximum memory footprint of the application.

for i in paths.indices {
    autoreleasepool {
        // all your image resizing code goes here
    }
}