6

I'd like to learn about memory management in Objective-C which I find not that easy because I'm fairly new at Objective-C and ARC and I'm mostly used to script languages for which I don't have to deal that much (or not at all) with memory management.

The app I'm working on is presenting a viewController (with xib file attached) from code after the press of a button. In this view controller I have several views instantiated; I record a sequence of images (photo's from the camera, saved to disk) which I convert to a movie and I have a gps tracker (mapKit) which display's a little map on screen. After all is done I can push a 'done' button which calls [self dismissViewControllerAnimated:YES completion:nil];

The viewController is animated back to my rootViewController and because I put an NSLog message inside the dealloc method in the viewController that is being dismissed I can confirm this viewController is being deallocated.

The problem is that I see the memory rise after the use of the app (usage consists of taking pictures and recording gps locations on a MapKit map as well as generate a movie file) to about 80 MB and this drops to about 70MB when I press 'done' so the viewController dismisses and the app returns to my rootViewController. I can present the same viewController again, use it and dismiss it, and the app will still occupy around 70MB of memory which doesn't drop. This does not really look like a memory leak to me because in that case I would expect a steady rise of memory with every instantiation and dismissal of the viewController. This isn't the case even if I have different buttons in my rootViewController which all instantiate a new and unique instance of my viewController class.

I am wondering: Is there something I should look for or is this expected behavior? Maybe the app is caching classes for future use? With memory management done right, should I be expecting an app to revert to 'virgin' memory state (in this case this would be around 4 MB) after dismissal of the only viewController that was presented?

Hype1
  • 71
  • 1
  • 8
  • 1
    Profile the app using *Leaks* under `Instruments`. – trojanfoe May 14 '15 at 20:08
  • Done, no leaks detected. – Hype1 May 14 '15 at 20:10
  • You may want to read [this Q&A](http://stackoverflow.com/q/12641658/335858), it talks about MapKit memory issue. The Q&A is old, though, so it may have been addressed. – Sergey Kalinichenko May 14 '15 at 20:10
  • @dasblinkenlight Very interesting, I had no idea. Thanks for linking to that. – matt May 14 '15 at 20:12
  • When I remove every use and reference to a class that uses MapKit my app is only recording images (from camera, and converting a sequence to a movie) and after first instantiation and use of the viewController it rises from about 4MB to 8MB and it stays at 8MB when the viewController is dismissed (again dealloc is called, I checked with NSLog). – Hype1 May 14 '15 at 20:24
  • Images are often cached to improve performance, maybe that's it. – Everton Cunha May 14 '15 at 20:33
  • dude, I hope you are not testing memory on simulator :) it's a whole different world. – Yaro Jul 20 '16 at 23:36

2 Answers2

10

If you are seeing this memory rise in Xcode and not when using instruments then the answer I have come up with is in this answer.

You can read that whole answer, it's pretty in depth. But long story short, in Xcode you are seeing the amount of memory that the OS has "given" to your app to use. This will increase any time your app tries to allocate something. It does not decrease as fast because the OS does performance guesses thinking your app may need more memory in the future. It is faster for the OS to leave that memory "given" to your app than to take it away and give it back later.

Community
  • 1
  • 1
Putz1103
  • 6,211
  • 1
  • 18
  • 25
  • 1
    Wow, thanks a lot! I've been looking for faults in my app code and reading up on ARC and memory management all day and it never occurred to me that the memory value would have something to do with memory assigned by the OS instead of actually needed at that moment. I had only this app active and for the test I activated a few 3D games as well and then I noticed the memory usage of my app drop instantly. I lost a day of work but I sure learned a lot. :) – Hype1 May 14 '15 at 22:08
3

The view controller should be cleared out from memory when it is not being used by other objects (or have no strong connections to your other objects that are not yet removed from memory).

Ex.

class ViewController: UIViewController {
    var secondViewController: SecondViewController?
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if let identifier = segue.identifier {
            if identifier == "second" {
                if secondViewController == nil {
                    secondViewController = segue.destinationViewController as? SecondViewController
                } else {
                    println("There's still an instance of second view controller")
                }
            }
        }
    }
}

Let's say you presented the secondViewController the first time using the storyboard segue, and store it in your instance of a ViewController as a property. Then, you dismiss the secondViewController, and present again the secondViewController from ViewController, it will print "There's still an instance of second view controller" since the one you presented earlier was still being used by ViewController.

However, when secondViewController has a weak connection, (weak var secondViewController: SecondViewController), it will never print, since from the moment the secondViewController was dismissed, it will be removed from memory and secondViewController will be nil.

EDIT:

Note: Result should be the same when using Objective-C.

chrisamanse
  • 4,289
  • 1
  • 25
  • 32