Приложение iOS - Предупреждение о памяти при рисовании с использованием cgcontextref - PullRequest
1 голос
/ 31 января 2012

Я занимаюсь разработкой приложения, в котором я рисую в методе 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]);
}

UPDATE:

Сбой повторился снова в том же потоке. Это произошло через 8 часов после перезагрузки устройства. Я не использовал приложение в течение целых 8 часов. После того, как я перезагрузил устройство, Приложение вообще не падает в этом конкретном потоке.

1 Ответ

1 голос
/ 01 февраля 2012

1) исправьте имя метода getCurrentZoomLevelIntervalList, возможно, просто `currentZoomLevelIntervalList ', это просто вызвало путаницу у других разработчиков и ARC.

2) Запустите Analyzer и исправьте все предупреждения.

3) Используйте инструменты для проверки потери памяти из-за оставшейся, но не просочившейся памяти.Последний является неиспользованной памятью, на которую все еще указывают.Используйте Heapshot в инструменте Allocations на инструментах.

Чтобы узнать, как использовать Heapshot для поиска разрыва памяти, см .: bbum blog

По сути, существует метод для запуска инструмента выделения инструментов,сделайте снимок кучи, запустите интуицию вашего кода и повторите повторение снимка кучи 3 или 4 раза.Это будет указывать на память, которая выделяется и не освобождается во время итераций.

Чтобы выяснить результаты, откройте для просмотра отдельные распределения.

Если вам нужно увидеть, где происходят сохранения, релизы и авто-релизыдля объекта используйте инструменты:

Запустите на инструментах, в Allocations включите "Record reference counts" on (вы должны остановить запись, чтобы установить опцию).Заставьте сборщик запустить, остановить запись, найти там ivar (datePickerView), выполнить детализацию, и вы сможете увидеть, где произошли все сохранения, выпуски и автоматические выпуски.

...