iPad 内存限制
我正在开发的应用程序相对简单,但它会抛出内存警告。我试图弄清楚应用程序设计是否需要太多内存,应该重新设计和分解以减少使用,或者应用程序设计很好,但应用程序本身臃肿并且错误地消耗了超出所需的内存。
该应用从网络下载一个包含一组问题的 XML 文件,然后生成一个显示问题控件列表的 UIScrollView。每个问题控件都有一个 UITextView 和一个 UISegmentedControl、UIButton、UITableView、UITextField 或四个带有 UIButton(自定义日期控件)的 UITextField。这是一个屏幕截图:
此设置非常适合较小的问题集但应用程序开始抛出内存警告,其中包含超过 120 个问题的较大集合。以下是在较大集合上使用分配和 VM Tracker Instruments 的典型运行:
分配内存在 xml 下载和模型加载时出现峰值,但直到分配内存达到稳定状态后才会引发警告。不过,当它们被抛出时,VM Tracker 内存仍在增加,这让我认为控件仍在加载到内存中,并且 VM Tracker 是导致警告的内存增长的更好指标。当驻留大小超过 125 MB 时,通常会出现警告。 我找到了一种方法来显着降低 Resident 大小。问题控件有一个自定义视图,可以为它们提供圆角边缘和阴影。如果我从自定义视图中注释掉 drawRect 代码(如下所示),分配内存将保持不变,但驻留大小会下降约 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 能够在内存中处理所有这些内容,我宁愿不将它们分解。任何意见都将受到高度赞赏。
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:
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:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您分配的每个视图都将占用大量内存。当屏幕上(或滚动视图中的屏幕外)有大量视图时,避免使用大量内存的方法是拥有一个可重复使用的视图池,并且任何时候只比屏幕上的视图多一些。
坏消息:这种缓存和交换的设置相当复杂。
好消息:UITableView 为您做到了!
当你有任意数量的 UIView 时,最好的解决方案几乎总是将它们放入表视图中,并让 Apple 来完成这项艰苦的工作。
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.
您可以使用 堆快照分析(使用 Instruments)来监控内存增量直至分配回溯详细信息 - 这应该让您充分了解什么是增长以及原因。这些分配通常表明您在此期间还应该销毁哪些内容。
还要确保您的程序中没有泄漏。
You can use heap shot analysis (using Instruments) to monitor the memory deltas down to allocation backtrace detail -- that should give you a good enough idea of what is growing and why. Those allocations often indicate what you should have also destroyed during the period.
Also be sure there are no leaks in your program.