1

I'm having an issue with CoreImage's CIImage when using it to load multiple images in a Swift 4 project on macOS Mojave using Xcode 10-latest.

I'm using code similar to this:

@IBAction func loadImages(sender: Any?) {
        let panel = NSOpenPanel()
        panel.allowsMultipleSelection = true
        panel.allowedFileTypes = [kUTTypeImage as String]
        let result = panel.runModal()

        if (result.rawValue == NSFileHandlingPanelOKButton) {
            for url in panel.urls {
                let image = CIImage(contentsOf: url)
                print(image!.extent.width)
            }
        }
    }

If I use this code & load a good amount of larger, high-quality images, my app will consume hundreds of MBs of RAM even long after that function has run for no apparent reason. It seems that the CIImage objects are just not being released even after they are no longer being used inside this function.

Having found two answers to similar problems (answer 1 & answer 2) I would've assumed that wrapping the code dealing with CIImages inside an autoreleasepool{} clojure would solve my problem, but the issue still persists when my code looks like so:

@IBAction func loadImages(sender: Any?) {
        autoreleasepool {
            let panel = NSOpenPanel()
            panel.allowsMultipleSelection = true
            panel.allowedFileTypes = [kUTTypeImage as String]
            let result = panel.runModal()

            if (result.rawValue == NSFileHandlingPanelOKButton) {
                for url in panel.urls {
                    let image = CIImage(contentsOf: url)
                    print(image!.extent.width)
                }
            }
        }
    }

Am I just missing some sort of fundamental knowledge of Swift memory management basics here or is this actually a bug that I have to somehow work around?

Any help would be greatly appreciated.

Skye Ewers
  • 358
  • 1
  • 4
  • 16
  • 1
    Not sure this will do it (it shouldn't), but more of a semantic thing, but put `autoreleasepool` around only the part that needs to be released, i.e. the creation of the images. `for url in panel.urls { autoreleasepool { ... } }` – impression7vx Aug 12 '19 at 02:02

1 Answers1

1

The solution to this problem was rather easy: There was no memory leak and the CIImage were not being retained for longer than they should've been.

macOS "Activity Monitor" as well as Xcode's basic views for resource usage show the amount of memory that macOS thinks a process will need and thus allocates to it.

When you run a memory intensive app it'll retain that allocation, without actually using any memory, even after the memory intensive tasks have been completed and the objects removed from RAM.

Loading that many CIImages caused macOS to allocate a lot of memory to my app, in order to accommodate its reserver intensive task. Since it can't predict / recognize when that task is done, the app retains that memory allocation without actually using it. This is the case until macOS needs memory for another more current task or your app quits.

Skye Ewers
  • 358
  • 1
  • 4
  • 16