4

I have an iPad app which is crashing on iPad (First model) as it is running out of memory.

In the app I have a main view which adds as subviews about 20 UIScrollViews (custom class) each containing a UIImageView and UIImage. When the user moves to the next page, I remove all these subviews from the superview and then add 20 new UIScrollViews to the same view.

If I profile the app for allocations and memory leaks everything is ok - the memory allocated stays at about 2MB while the user scrolls left and right.

However if I look at the real memory usage in the Activity Monitor I can see that every time the user moves to a new page, the real memory increases by about 20MB. Eventually after a few new pages the app size hits 150+ MB and crashes.

Can anyone suggest what might cause this type of behaviour and how I can further troubleshoot this ?

Just a bit more info on the app structure :

  • In view did load the images are loaded into an NSMutableArray using initWithContentsOfFile.
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
GuybrushThreepwood
  • 5,598
  • 9
  • 55
  • 113

1 Answers1

1

You should not be maintaining these images in an array. Images consume a disproportionate amount of your limited RAM. There are a couple of approaches:

  1. If you want to keep it simple, just don't store the images anywhere. Load the image property of the UIImageView by loading the image via initWithContentsOfFile and call it a day.

  2. If you want some RAM caching for performance reasons, you could use imageNamed instead of initWithContentsOfFile. When the app receives a memory warning, the cache will automatically be purged.

  3. I'd be inclined to use initWithContentsOfFile, but then manually cache in my own NSCache (which is like a NSDictionary, except you can set a countLimit of how many images it should hang on to).

By the way, you don't describe what technically happens when "the user moves to the next page." If you're simply refreshing the existing controls on the existing view controller, then everything is probably fine (once you fix the NSMutableArray problem I discuss above). If you're pushing/presenting to another view controller or scrolling controls off screen but neglecting to remove the old ones from their superview, then that will also cause problems. You might want to clarify what you're doing there.

Bottom line, you just need to make sure that when you go from one page to another, that you're not maintaining strong references to any old images or controls.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • This is all happening within the same UIView. The objects are added to the view, removed and then new (in this case a custom UIScrollView) objects are added. I'm still not clear on my original question - why is the real memory increasing only at the point where new objects are added to the view (via self.view addSubview x) ? The objects are placed in the array in the viewDidLoad method and the real memory doesn't increase at this point (it's low and constant). – GuybrushThreepwood Apr 27 '13 at 17:00
  • @Ohnomycoco In that case, we probably need to see some source code to diagnose the problem. But clearly you're adding something as you go to the next page. It's impossible to diagnose on the basis of what you've shared so far. – Rob Apr 27 '13 at 17:11
  • @Ohnomycoco You can also use the Allocations instrument (as illustrated [here](http://stackoverflow.com/a/14105056/1271826)) to identify jumps in your allocations, highlight the portion of the chart, and it will show you precisely what's causing the consumption of memory. – Rob Apr 27 '13 at 18:41
  • Thanks. It looks like images are not really loaded until they are placed on the screen. From an app perspective there is no increase in memory when the images appear on screen, but from an iPad real memory perspective it is clear more memory is used up when the images are actually placed on the screen. – GuybrushThreepwood Apr 28 '13 at 21:11