问题
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