3

Is there a 'nuclear option' to release the images from the image array? I would like to play the first animation1 (ImageSet1), then in the completion block delete this animation and then load and play the second animation2 (ImageSet2), and so on: wash, rinse, repeat - you get it :)

First, I define the instance variables of my ViewController:

var animation1: [UIImage] = []
var animation2: [UIImage] = []
var animation3: [UIImage] = []

Then I create an Animation Array for each animation:

func createImageArray(total: Int, imagePrefix: String) -> [UIImage]{
    var imageArray: [UIImage] = []
    for imageCount in 0..<total {
    let imageName = "\(imagePrefix)-\(imageCount).png"
    let image = UIImage(named: imageName)!
    imageArray.append(image)
    }
    return imageArray
    }

Then I set the animate values:

func animate(imageView: UIImageView, images: [UIImage]){
    imageView.animationImages = images
    imageView.animationDuration = 1.5
    imageView.animationRepeatCount = 1
    imageView.startAnimating() }

    animation1 = createImageArray(total: 28, imagePrefix: "ImageSet1")
    animation2 = createImageArray(total: 53, imagePrefix: "ImageSet2")
    animation3 = createImageArray(total: 25, imagePrefix: "ImageSet3")

And lastly call the animate function

func showAnimation() {
    UIView.animate(withDuration: 1, animations: {
        animate(imageView: self.animationView, images: self.animation1)

        }, completion: { (true) in

        // Release the Images from the Array

        })
    }

I would like to release the images from the image array in the completion block to lower my memory footprint, but I can't seem to get this to work, I have tried all four examples below but there is no effect on the memory footprint:

func showAnimation() { 
UIView.animate(withDuration: 1, animations: { 
animate(imageView: self.animationView, images: self.animation1) 

}, completion: { (true) in 

self.animation1 = [] // is this correct?
self.animationView.image = nil // also doesn't work
self.animationView.removeFromSuperview() // also doesn't work
self.animation1 = nil // also doesn't work

}) 
}

After the completion block, I set the animation1 array equal to [] and it does remove the animation (you can't see it any more) but the memory footprint remains the exact same (I have also tried the other three options as well).

With the above, the memory footprint 'bumps' up each time I add the next animation and it eventually causes the OS to terminate the App

Even when you change ViewControllers, the array is still holding the images in memory

Thanks for any help :)

4
  • what about self.animation1.removeAll()? Commented Dec 10, 2017 at 5:33
  • 1. See here and maybe here. 2. If the images are being referenced and retained from any other line in your code, then it needs it requires to be released from there as well. Additionally you should change completion: { (true) in to completion: { [weak self] (true) in so you avoid capturing self and creation of memory cylcles Commented Dec 10, 2017 at 5:48
  • Hi @TusharSharma - thanks for your answer, I tried self.animation1.removeAll() and there is still no effect on memory (it remains the same) Commented Dec 10, 2017 at 8:14
  • Thanks @Honey - is there a 'nuclear' option to release all references to the image array in one line? Also, if we call the animation in two different lines of code (in two separate functions), how would you address each line to release the animation (ie either in the completion block or in a simple function)? Commented Dec 10, 2017 at 17:27

1 Answer 1

0

UIImage(named: ) will always save the image in the memory stack unless there is a requirement for more memory and enough time to deallocate.

In order to release images from memory you should use the other constructor: UIImage(contentsOfFile: ) and save the images in folder instead of the Asset manager. Maybe data will work as well but i'm not sure.

Temporary / Large resources will consume the heap, you should use "temp saving" methods such as contentsOfFile to clear it from the memory.

Sign up to request clarification or add additional context in comments.

3 Comments

I'd create an external folder named "Animations" move the animations there (outside of the assets - because you can't get a path for the assets), and then use: Bundle.main.path(forResource: ofType: ) to load the path's of the animation images, and use UIImage(contentsOfFile: ____) with the given path
Are you sure the images are part of the project and you are using the correct names (without extension)? because if Bundle.main.path(forResource) returns nil it means it can't load the images, maybe try and clean the project prior to re-compiling. Which parameter is nil? the bundlePath or the image?
Hi @unkgd - appreciate your answers. I have created a new question in light of your comments and if you would like to post here I will accept your answer: stackoverflow.com/questions/47744665/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.