0

给出以下任务:

  • 扫描一个文件夹,其中包含带有图像的子文件夹,并确保没有任何图像损坏
  • 使用 MacOS 和 Swift
  • 打开每个图像并检查它是否有损坏

我写了这个小小的命令行程序:

import ArgumentParser
import AppKit
import Foundation

struct CheckImages: ParsableCommand {
    @Option(help: "The images root directory")
    var path: String

    func run() throws {
        let directories = try FileManager.default.contentsOfDirectory(atPath: path)

        for directory in directories {
            if directory == ".DS_Store" {
                continue
            }

            let prefix = self.path + "\(directory)/PREFIX_\(directory)"

            let imageName = prefix + ".jpg"
            let image = NSImage(contentsOfFile: imageName)
            if image == nil {
                print("PROBLEM \(imageName)")
            }
        }
    }
}

CheckImages.main()

每张图片大小约为 20MB。我总共有大约 150.000 张图像要检查。

不幸的是,XCode 以Program ended with exit code: 9. 深入挖掘(使用 Instruments)结果证明这个小帮助应用程序消耗了我所有的内存NSImage.init()。作为NSImage一个成熟的对象,我怀疑它有什么问题。因此,我的问题是,有人可以向我解释这种行为吗?

我的环境:

  • XCode 版本 11.4.1 (11E503a)
  • Apple Swift 版本 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51)
4

1 回答 1

0

回答我自己的问题,我需要一个自动释放池。因为我从来没有在 Objective-C 中编程,所以我不知道诸如自动释放池之类的东西。由于NSImage“只是”一个围绕 ObjC-NSImage 对象的包装器,它需要一个自动释放池来管理释放。我们在 2020 年,我们必须以这种方式管理这些事情?

在这篇文章中,我找到了上述问题的答案:是否有必要在 Swift 程序中使用 autoreleasepool?

另一个不错的帖子可以在这里找到:https ://swiftrocks.com/autoreleasepool-in-2019-swift.html

因此,上面的代码必须如下所示:

import ArgumentParser
import AppKit
import Foundation

struct CheckImages: ParsableCommand {
    @Option(help: "The images root directory")
    var path: String

    func run() throws {
        let directories = try FileManager.default.contentsOfDirectory(atPath: path)

        for directory in directories {
            if directory == ".DS_Store" {
                continue
            }

            autoreleasepool {
                let prefix = self.path + "\(directory)/PREFIX_\(directory)"

                let imageName = prefix + ".jpg"
                let image = NSImage(contentsOfFile: imageName)
                if image == nil {
                    print("PROBLEM \(imageName)")
                }
            }
        }
    }
}

CheckImages.main()
于 2020-04-22T06:24:41.647 回答