Как нарисовать на постоянном холсте и нарисовать его внутри вида? - PullRequest
0 голосов
/ 01 июня 2011

Я пишу небольшое приложение для рисования для iOS. Я подклассифицирую объявление UIView, выполняющее вычисления внутри его drawRect: метод. Все было хорошо, пока у меня не появилось много объектов (на самом деле полилиний), а затем производительность начала ухудшаться.

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    CGContextRef imageContext = UIGraphicsGetCurrentContext();

    int i, j;
    for(i = 0; i < [_strokes count]; i++) {
        NSMutableArray *stroke = [_strokes objectAtIndex:i];
        if([stroke count] < 2) {
            continue;
        }
        CGContextSetStrokeColorWithColor(imageContext, [[_penColours objectAtIndex:i] CGColor]);
        for(j = 0; j < [stroke count]-1; j++) {
            CGPoint line[] = {
                [[stroke objectAtIndex:j] CGPointValue],
                [[stroke objectAtIndex:j+1] CGPointValue]
            };

            CGContextSetLineWidth(imageContext, _brushSize);
            CGContextSetLineCap(imageContext, kCGLineCapRound);
            CGContextSetLineJoin(imageContext, kCGLineJoinRound);

            CGContextAddLines(imageContext, line, 2);
            CGContextStrokePath(imageContext);
        }
    }

    CGContextFlush(imageContext);
}

где _strokes - массив массивов точек. Моя первая идея состояла в том, чтобы сделать изображение в виде ивара, нарисовать его в контексте, нарисовать дополнительные штрихи в контексте (измените j = 0 на j = [stroke count] - 2), захватить контекст в изображение и сохранить его обратно в ивар , Не сработало.

Затем я попробовал многие другие дороги, которые не стоит упоминать, пока не нашел другой вопрос по SO ( производительность Quartz2D - как улучшить ). К сожалению, это не сработало, как я ожидал, поскольку мне пришлось сохранить изображение, что привело к предупреждению памяти 1, 2, падению.

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    UIGraphicsBeginImageContext(CGSizeMake(1024, 768));
    CGContextRef imageContext = UIGraphicsGetCurrentContext();

    if(_image != nil) {
        CGContextDrawImage(imageContext, CGRectMake(0, 0, 1024, 768), [_image CGImage]);
    }

    int i, j;
    for(i = 0; i < [_strokes count]; i++) {
        NSMutableArray *stroke = [_strokes objectAtIndex:i];
        if([stroke count] < 2) {
            continue;
        }
        CGContextSetStrokeColorWithColor(imageContext, [[_penColours objectAtIndex:i] CGColor]);
        for(j = [stroke count]-2; j < [stroke count]-1; j++) {
            CGPoint line[] = {
                [[stroke objectAtIndex:j] CGPointValue],
                [[stroke objectAtIndex:j+1] CGPointValue]
            };

            CGContextSetLineWidth(imageContext, _brushSize);
            CGContextSetLineCap(imageContext, kCGLineCapRound);
            CGContextSetLineJoin(imageContext, kCGLineJoinRound);

            CGContextAddLines(imageContext, line, 2);
            CGContextStrokePath(imageContext);
        }
    }

    _image = UIGraphicsGetImageFromCurrentImageContext();
    [_image retain];
    UIGraphicsEndImageContext();

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, CGRectMake(0, 0, 1024, 768), [_image CGImage]);
}

1 Ответ

1 голос
/ 01 июня 2011

Похоже, по крайней мере, часть проблемы в том, что вы сохраняете _image, но никогда не выпускаете его.Каждый раз, когда вы присваиваете _image новое значение, вы пропускаете предыдущее изображение, и это очень быстро заполняет память.

Помимо этого, вам, вероятно, следует использовать CGLayer для вашего закадрового рисунка, а не растрового изображения.Вы можете рисовать в слое в любое время, а затем просто скопировать его на экран в вашем -drawRect: метод.

...