iOS 应用程序 - 使用 cgcontextref 绘图时出现内存警告
我正在开发一个应用程序,在其中使用自定义类的drawRect方法进行绘图。
我在视图的图形上下文中绘制线条。当我使用 setNeedsDisplay 一次又一次地重绘它们时,我收到内存警告,并且我的应用程序立即崩溃。
我检查了我的drawRect代码中是否有任何泄漏。我什么也没找到。内存分配也没有显示出任何重大差异。
问题解决了一次,iOS 设备被重新启动。但我确信崩溃将会再次重演。可能是什么问题。你们中有人遇到过类似的问题吗?
代码如下:
- (void)drawRect:(CGRect)rect{
[self drawTheTimeLineHorizontally];
}
- (void) drawTheTimeLineHorizontally {
//Get the current graphics context
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
[UIColorFromRGB(kCalendarTimeLineColor) setStroke];
CGContextSetLineWidth(currentContext, 1);
CGMutablePathRef path = CGPathCreateMutable();
NSArray *hours = [self currentZoomLevelIntervalList];
int numHours = [hours count];
for (int i = 0; i < numHours; ++i) {
CGPathMoveToPoint(path, NULL, 0, (i+kMultiplierTopDailyCalendarTimeline)*offset+2);
[self drawHoursLeftOfLines:[hours objectAtIndex:i] withContext:currentContext withRect:CGRectMake(kOriginXOfTextInTimeLine, (i+kMultiplierTopDailyCalendarTimeline)*offset+(offset/3), kWidthOfTextInTimeLine, offset/3)];
[UIColorFromRGB(kCalendarTimeLineColor) setStroke];
CGPathAddLineToPoint(path, NULL, widthOfDailyCalendar+orginXEventTile, ((i+kMultiplierTopDailyCalendarTimeline)*offset+2));
}
CGPathMoveToPoint(path, NULL, 0, (numHours+kMultiplierTopDailyCalendarTimeline)*offset+2);
CGPathAddLineToPoint(path, NULL, widthOfDailyCalendar+orginXEventTile, (numHours+kMultiplierTopDailyCalendarTimeline)*offset+2);
CGContextAddPath(currentContext, path);
CGContextDrawPath(currentContext, kCGPathStroke);
//CGContextClosePath(currentContext);
CGPathRelease(path);
//Restore the saved context
CGContextRestoreGState(currentContext);
}
- (void) drawHoursLeftOfLines:(NSString*) time withContext:(CGContextRef) context withRect:(CGRect) contextRect {
[UIColorFromRGB(kTimeLineHourTextColor) setStroke];
CGContextSelectFont(context, kTimeLineHourTextFontStyle , kFontSizeTimeLineText, kCGEncodingMacRoman);
CGContextSetCharacterSpacing (context, 1);
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
CGAffineTransform xform = CGAffineTransformMake(
1.0, 0.0,
0.0, -1.0,
0.0, 0.0);
CGContextSetTextMatrix(context, xform);
CGContextShowTextAtPoint(context, contextRect.origin.x, contextRect.origin.y, [time cStringUsingEncoding:NSASCIIStringEncoding], [time length]);
}
更新:
崩溃在同一流程中再次重复。设备重新启动后 8 个多小时后发生这种情况。我已经整整 8 个小时没有使用该应用程序了。重新启动设备后,应用程序在该特定流程中根本不会崩溃。
I am developing an application where I am drawing in drawRect method of a customClass.
I draw lines in the Graphics context of the View. When I redraw them again and again using setNeedsDisplay, I get memory warnings and my App immediately crashes.
I checked if there were any leaks in my drawRect code. I found nothing. The memory allocation also did not show any major difference.
The problem got fixed once, the iOS device was rebooted. But I am sure the crash will be repeated again. What could be the problem. Have any of you faced similar problems?
The code is below:
- (void)drawRect:(CGRect)rect{
[self drawTheTimeLineHorizontally];
}
- (void) drawTheTimeLineHorizontally {
//Get the current graphics context
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
[UIColorFromRGB(kCalendarTimeLineColor) setStroke];
CGContextSetLineWidth(currentContext, 1);
CGMutablePathRef path = CGPathCreateMutable();
NSArray *hours = [self currentZoomLevelIntervalList];
int numHours = [hours count];
for (int i = 0; i < numHours; ++i) {
CGPathMoveToPoint(path, NULL, 0, (i+kMultiplierTopDailyCalendarTimeline)*offset+2);
[self drawHoursLeftOfLines:[hours objectAtIndex:i] withContext:currentContext withRect:CGRectMake(kOriginXOfTextInTimeLine, (i+kMultiplierTopDailyCalendarTimeline)*offset+(offset/3), kWidthOfTextInTimeLine, offset/3)];
[UIColorFromRGB(kCalendarTimeLineColor) setStroke];
CGPathAddLineToPoint(path, NULL, widthOfDailyCalendar+orginXEventTile, ((i+kMultiplierTopDailyCalendarTimeline)*offset+2));
}
CGPathMoveToPoint(path, NULL, 0, (numHours+kMultiplierTopDailyCalendarTimeline)*offset+2);
CGPathAddLineToPoint(path, NULL, widthOfDailyCalendar+orginXEventTile, (numHours+kMultiplierTopDailyCalendarTimeline)*offset+2);
CGContextAddPath(currentContext, path);
CGContextDrawPath(currentContext, kCGPathStroke);
//CGContextClosePath(currentContext);
CGPathRelease(path);
//Restore the saved context
CGContextRestoreGState(currentContext);
}
- (void) drawHoursLeftOfLines:(NSString*) time withContext:(CGContextRef) context withRect:(CGRect) contextRect {
[UIColorFromRGB(kTimeLineHourTextColor) setStroke];
CGContextSelectFont(context, kTimeLineHourTextFontStyle , kFontSizeTimeLineText, kCGEncodingMacRoman);
CGContextSetCharacterSpacing (context, 1);
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
CGAffineTransform xform = CGAffineTransformMake(
1.0, 0.0,
0.0, -1.0,
0.0, 0.0);
CGContextSetTextMatrix(context, xform);
CGContextShowTextAtPoint(context, contextRect.origin.x, contextRect.origin.y, [time cStringUsingEncoding:NSASCIIStringEncoding], [time length]);
}
UPDATE:
The crash got repeated again in the same flow. This happened after over 8 hours after the device was rebooted. I have not used the App for whole 8 hours. After I rebooted the device, the Application does not crash in that Particular flow at all.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
1)更正方法名称
getCurrentZoomLevelIntervalList
,也许只是“currentZoomLevelIntervalList”,它只会给其他开发人员和ARC造成混乱。2) 运行分析器并修复所有警告。
3)使用仪器检查是否由于内存保留而不是泄漏而导致内存丢失。后者是仍然指向的未使用的内存。在 Instruments 的分配工具中使用 Heapshot。
有关如何使用 Heapshot 查找内存浪费,请参阅:bbum blog
基本上有一种方法是运行 Instruments 分配工具,进行一次堆快照,运行代码的直觉,然后重复 3 或 4 次另一个堆快照。这将指示迭代期间分配但未释放的内存。
要了解结果,请查看单独的分配情况。
如果您需要查看对象在何处发生保留、释放和自动释放,请使用仪器:
在仪器中运行,在分配中将“记录引用计数”设置为打开(您必须停止记录才能设置该选项)。使选择器运行,停止记录,搜索 ivar (datePickerView),向下钻取,您将能够看到所有保留、释放和自动释放发生的位置。
1) correct the method name
getCurrentZoomLevelIntervalList
, perhaps just `currentZoomLevelIntervalList', it just caused confusion to other developers and ARC.2) Run Analyzer and fix all warnings.
3) Use instruments to check for memory loss due to retained but not leaked memory. The latter is unused memory that is still pointed to. Use Heapshot in the Allocations instrument on Instruments.
For HowTo use Heapshot to find memory creap, see: bbum blog
Basically there method is to run Instruments allocate tool, take a heapshot, run an intuition of your code and another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.
To figure out the results disclose to see the individual allocations.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on on (you have to stop recording to set the option). Cause the picker to run, stop recording, search for there ivar (datePickerView), drill down and you will be able to see where all retains, releases and autoreleases occurred.