Swift5 MacOS ImageResize memory issue

偶尔善良 提交于 2021-02-02 03:43:50

问题


I am new to Mac OS App Development with Swift. But I tried to make the simple ImageResizer app. I have to resize 50k images. After 10 hours, the memory has increased to nealy 120GB. I thought Swift also has Garbage collector. Why does it increase memory? I will show you my code.

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

回答1:


You can put your whole code that it is inside your loop inside an 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
    }
}



回答2:


Swift uses ARC (Automatic Reference Counting) which means objects will be deallocated when the number of strong references to that object reaches zero. I don't immediately see in the code provided where the problem is, but I suspect there must be some location elsewhere in your code where you are holding a reference to the images.



来源:https://stackoverflow.com/questions/62201378/swift5-macos-imageresize-memory-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!