The problem

You have loads of operations to perform with a for loop, the app is running out of memory and eventually is crashing.

It happened to most of us. It happened to me when i wanted to create thumbnail images for Zuper during the app’s startup.

The solution

Many of those times that we run ouf memory, an autorelease pool can do magic. Take a look on the code below:

import UIKit

extension UIColor {
    static func randomColor() -> UIColor {
        return UIColor(
            red: CGFloat(arc4random_uniform(255)) / 255,
            green: CGFloat(arc4random_uniform(255)) / 255,
            blue: CGFloat(arc4random_uniform(255)) / 255,
            alpha: 1
        )
    }
}

class ViewController: UIViewController {
    @IBOutlet weak var onOff: UISwitch!

    @IBAction func startCaching() {
        print("Saving images to \(NSTemporaryDirectory())")
        for i in 1...200 {
            if onOff.on {
                autoreleasepool { () -> () in
                    cacheAnImage("\(i).png")
                }
            } else {
                cacheAnImage("\(i).png")
            }
        }
    }

    func cacheAnImage(fileName:String) {
        print("Caching image \(fileName)")
        let aLayer = CALayer()
        aLayer.frame = view.bounds
        let subLayerSide = UIScreen.mainScreen().bounds.size.width / 10
        for i in 0...10 {
            for j in 0...Int(UIScreen.mainScreen().bounds.size.height / subLayerSide) {
                let tempLayer = CALayer()
                tempLayer.frame = CGRect(
                    x: CGFloat(i) * subLayerSide,
                    y: CGFloat(j) * subLayerSide,
                    width: subLayerSide,
                    height: subLayerSide
                )
                tempLayer.backgroundColor = UIColor.randomColor().CGColor
                aLayer.addSublayer(tempLayer)
            }
        }
        UIGraphicsBeginImageContextWithOptions(aLayer.bounds.size, false, 2)
        let context = UIGraphicsGetCurrentContext()
        aLayer.renderInContext(context!);
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        if let data = UIImagePNGRepresentation(img) {
            data.writeToFile(NSTemporaryDirectory() + fileName, atomically: false)
        }
    }
}

The cacheAnImage function, creates a random image - same size as the screen - and stores it in the /tmp directory. If you perform this function 200 times without using an autoreleasepool the app will crash (Assuming you run this app on a device and not on the emulator). Thats not the case if you are using an autorelease pool.

Below i have a video that demonstrates it. Keep your eye on the memory usage on the right hand side.

Sending a release message at every pass of the loop, might affect the performance a little bit but at least your app will not crash.

You can download and test this project from here.