Search code examples
objective-ciosmemory-warning

iPad Memory Limitations


The app I'm working on is relatively simple but it is throwing memory warnings.  I'm trying to figure out whether the app design needs too much memory and should be redisigned and broken up to use less or the app design is fine but the app itself is bloated and incorrectly gobbling up more memory than needed.

The app downloads an XML file from the web that contains a set of questions and then generates a UIScrollView that displays a list of question controls.  Each question control has a UITextView and a UISegmentedControl, UIButton, UITableView, UITextField, or four UITextFields with a UIButton (custom date control).  Here is a screenshot:

http://i.imgur.com/vpa9Z.png

This setup works great for smaller question sets but the app starts throwing memory warnings with larger sets of over 120 questions.  Here is a typical run with the Allocations and VM Tracker Instruments on a larger set:

http://i.imgur.com/gyWOX.png

The Allocations memory spikes on the xml download and model load but the warnings are not thrown until after the Allocations memory has plateaued.  The VM Tracker memory is still increasing when they are thrown though, which makes me think the controls are still being loaded into memory and that the VM Tracker is the better indicator of the memory growth causing the warnings.  The warnings typically happen when the Resident Size gets greater than 125 MB.  I have found one way to lower the Resident size pretty considerably.  The question controls have a custom view to give them rounded edges and a drop shadow.  If I comment out the drawRect code (shown below) from the custom view the Allocations memory stays the same but the Resident Size drops about 30 MB and does not grow above 93 MB.  I can find a lighterwieght background for the questions but I would prefer to keep the rounded edges and drop shadow if I can get its memory footprint down.

- (void)drawRect:(CGRect)rect {
    // get the contect
    CGContextRef context = UIGraphicsGetCurrentContext();

    //for the shadow, save the state then draw the shadow
    CGContextSaveGState(context);
    CGContextSetShadow(context, CGSizeMake(4,-5), 10);

    //now draw the rounded rectangle
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);  

    if(_HighlightColor==nil){
        _HighlightColor = [[UIColor whiteColor] retain];
    }
    CGContextSetFillColorWithColor(context, _HighlightColor.CGColor);

    //since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame
    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30);
    CGFloat radius = 5;
    // the rest is pretty much copied from Apples example
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);

    // Start at 1
    CGContextMoveToPoint(context, minx, midy);
    // Add an arc through 2 to 3
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    // Add an arc through 4 to 5
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    // Add an arc through 6 to 7
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    // Add an arc through 8 to 9
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
    // Close the path
    CGContextClosePath(context);
    // Fill & stroke the path
    CGContextDrawPath(context, kCGPathFillStroke);

    //for the shadow
    CGContextRestoreGState(context);
}

Instruments and the memory warnings make it seem like the memory is maxed out but these numbers seem high to me.  I wouldn't think 120 of these question controls in a scrollview would be a problem for the iPad to handle but I don't have a frame of reference on how much memory they should use up.  Considering some of the graphic-intensive games that the iPad can run it does not seem like the simple drawRect code above would eat up over 30 MB in the question controls.  Does this memory usage seem high or is this what you would expect from an app with this many simple UI elements?  Is there something in the drawRect that would eat up a lot of memory or any suggestions on how to optimize it?  If it seems like this should max out the iPad's memory, I will create tabs or pages and limit the number of questions I put onto a tab/page so that only a fraction of the controls will be loaded into memory at one time.  However I would rather not break them up if the iPad should be able to handle them all in memory.  Any input is greatly appreciated.


Solution

  • Every view that you have allocated will take up significant memory. The way to avoid using tons of memory when you have a lot of views on screen (or off screen in a scrollview) is to have a pool of views that you reuse, only having a few more than are on screen at any time.

    Bad news: This caching and swapping is pretty complicated to set up.

    Good news: UITableView does it for you!

    When you have an arbitrarily large number of UIViews, the best solution is almost always to put them into a table view, and let Apple do the hard work.