iPad内存限制

时间:2012-02-07 07:07:04

标签: objective-c ios memory-warning

我正在处理的应用程序相对简单,但它会抛出内存警告。我正在试图弄清楚应用程序设计是否需要太多内存,应该重新分配并分解为使用更少或应用程序设计很好但应用程序本身是膨胀的并且错误地吞噬了比所需更多的内存。

应用程序从Web下载包含一组问题的XML文件,然后生成显示问题控件列表的UIScrollView。每个问题控件都有一个UITextView和一个UISegmentedControl,UIButton,UITableView,UITextField或带有UIButton的四个UITextField(自定义日期控件)。这是一个截图:

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

此设置适用于较小的问题集,但应用程序开始使用120多个问题的更大集合抛出内存警告。以下是使用Allocations和VM Tracker Instruments的典型运行:

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

分配内存在xml下载和模型加载时出现峰值,但是在分配内存达到平台之后才会抛出警告。 VM Tracker内存在被抛出时仍在增加,这使我认为控件仍然被加载到内存中,并且VM Tracker是内存增长的更好指示器,从而导致警告。当Resident Size大于125 MB时,通常会发生警告。 我找到了一种相当大的降低居民身材的方法。问题控件有一个自定义视图,为它们提供圆角和投影。如果我从自定义视图中注释掉drawRect代码(如下所示),则Allocations内存保持不变,但Resident Size下降大约30 MB并且不会增长到93 MB以上。我可以找到一个更清晰的问题背景,但如果我可以减少它的内存占用,我宁愿保持圆形边缘和阴影。

- (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);
}

仪器和内存警告使得内存看起来很大,但这些数字对我来说似乎很高。我不认为滚动视图中的120个问题控件对于iPad来说是一个问题,但我没有关于他们应该消耗多少内存的参考框架。考虑到iPad可以运行的一些图形密集型游戏,上面的简单drawRect代码似乎不会在问题控件中占用超过30 MB。这个内存使用量是否很高,或者这是您对具有这么多简单UI元素的应用程序的期望? drawRect中是否存在会占用大量内存或有关如何优化它的任何建议?如果看起来这应该最大化iPad的内存,我将创建选项卡或页面并限制我放在选项卡/页面上的问题数量,以便一次只将一小部分控件加载到内存中。但是,如果iPad能够在内存中处理它们,我宁愿不打破它们。任何意见都非常感谢。

2 个答案:

答案 0 :(得分:4)

您分配的每个视图都会占用大量内存。当你在屏幕上有很多视图(或滚动视图中的屏幕外)时,避免使用大量内存的方法是拥有一个可以重复使用的视图池,只需要在屏幕上显示多个视图。< / p>

坏消息:这种缓存和交换设置非常复杂。

好消息:UITableView为您做到了!

当你拥有任意数量的UIViews时,最好的解决方案几乎总是把它们放到表格视图中,让Apple付出艰苦的努力。

答案 1 :(得分:2)

您可以使用heap shot analysis(使用Instruments)监控内存增量到分配回溯详细信息 - 这应该可以让您充分了解正在增长的内容和原因。这些分配通常表明在此期间你应该销毁的东西。

还要确保程序中没有泄漏。