Приложение 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 часов. После того, как я перезагрузил устройство, Приложение вообще не падает в этом конкретном потоке.
1 ответ
1) исправить название метода getCurrentZoomLevelIntervalList
, возможно, просто `currentZoomLevelIntervalList', это просто вызвало путаницу у других разработчиков и ARC.
2) Запустите анализатор и исправьте все предупреждения.
3) Используйте инструменты для проверки потери памяти из-за оставшейся, но не утечки памяти. Последний является неиспользованной памятью, на которую все еще указывают. Используйте Heapshot в инструменте Allocations на инструментах.
Чтобы узнать, как использовать Heapshot для поиска утечки памяти, см. Блог bbum.
По существу, существует метод запуска инструмента выделения инструментов, создания кучи, запуска интуитивного кода и повторения кучи еще 3 или 4 раза. Это будет указывать на память, которая выделена и не освобождена во время итераций.
Чтобы выяснить результаты раскрыть, чтобы увидеть отдельные распределения.
Если вам нужно увидеть, где хранятся, выпускаются и автоматически выпускаются объекты, используйте инструменты:
Запустите инструменты, в разделе "Выделения" включите "Счетчик ссылок записи" (вы должны остановить запись, чтобы установить опцию). Заставьте сборщик запустить, остановить запись, найти там ivar (datePickerView), выполнить детализацию, и вы сможете увидеть, где произошли все сохранения, выпуски и авто-релизы.