3

I've created a new Xcode project that has only the following:

  • code creating an array of UIImages from png's dragged in to the project (I have tried both UIImage(named:) and UIImage(contentsOfFile:) when appending images to the array)
  • a UIImageView
  • a button which sets the imageView.animationImages = arrayOfImages and calls imageView.startAnimating()

When the button is pressed and the animation plays, the memory usage increases by 150-200MB, depending on the number of images in the image array. Then the memory usage remains at that level.

Setting imageView.animationImages = nil doesn't clear the memory. How could I go about clearing that memory?

Any suggestions would be helpful. Thanks!

RanLearns
  • 4,086
  • 5
  • 44
  • 81
  • Verify if it does it on device too. The Simulator has odd behaviour with some things. Also check if a “Trigger low memory warning” does a flush. – Warren Burton Jun 03 '18 at 17:03
  • This is basically a simplified repost of [your previous question](https://stackoverflow.com/questions/50661331/can-memory-in-my-code-be-better-managed-when-using-uiimageview-animationimages-a). – rmaddy Jun 03 '18 at 17:03
  • @rmaddy yes - I am trying to get to the root of the matter with a new project focused just on this issue – RanLearns Jun 03 '18 at 17:04
  • @WarrenBurton thanks for answering! Yes it is the same behavior on device, and triggering the memory warning does not clear the memory here either. – RanLearns Jun 03 '18 at 17:12
  • Does the memory go up each time the animation plays, or does it go up just the first time and stick at that level. This is of course above and beyond the memory needed to load the images in the first place? – vacawama Jun 03 '18 at 18:35
  • @vacawama goes up the first time and sticks at that level. Can continue to run that animation repeatedly with no additional memory usage. If you run a second animation, memory goes up another 150-200MB and sticks at that new level – RanLearns Jun 03 '18 at 20:12

1 Answers1

6

1. Don't implicitely cache images

I guess you are using UIImage(named:)?

This method caches the images, see: https://developer.apple.com/documentation/uikit/uiimage/1624146-init

Apple recommends:

If you have an image file that will only be displayed once and wish to ensure that it does not get added to the system’s cache, you should instead create your image using imageWithContentsOfFile:. This will keep your single-use image out of the system image cache, potentially improving the memory use characteristics of your app.

So using 'UIImage(contentsOfFile: String)' should solve your problem. Due to the documentation you need to supply a path to the image, the image name is not sufficient, see here:

https://developer.apple.com/documentation/uikit/uiimage/1624123-imagewithcontentsoffile

There it is also mentioned:

This method does not cache the image object.

2. Don't hold references to the images

When you are loading the images into a local array make sure to empty it.

self.imageArray = []

3. Set imageView.animationImages to an empty array

self.imageArray = []
self.imageView.animationImages = self.imageArray

Quick verification of the allocations in Instruments:

allocations in Instruments

As you can see the memory is reclaimed. All good.

Community
  • 1
  • 1
Stephan Schlecht
  • 26,556
  • 1
  • 33
  • 47
  • Oh man! I should have mentioned this - I tried using both imageNamed and imageWithContentsOfFile and the behavior is the same with either one. Any other thoughts? – RanLearns Jun 03 '18 at 18:23
  • No problem :-) I added two further potential issues. Also quickly verified it in Instruments. Memory is reclaimed. Let me know, if it works for you. – Stephan Schlecht Jun 03 '18 at 22:05
  • 1
    interesting! Thank you, that does indeed reclaim the memory. Strange that the memory isn't used when assigning the array of images to the local array. The memory hit only happens once the animation occurs. And yet removing the reference seems to be the only way to reclaim the memory. Thanks so much for trying this out and writing in! – RanLearns Jun 03 '18 at 23:58
  • UIImages are not immediately loaded and decoded, but at latest when an image is about to be displayed the image data must be decoded. That means width * height * 4 values (RGBA), which is memory-consuming. – Stephan Schlecht Jun 04 '18 at 20:36
  • Bonus info. Thanks again for taking the time to leave an answer here. =) – RanLearns Jun 04 '18 at 22:15