drawRect: сбой из-за большого прямоугольника после масштабирования

Моя структура UIView: у меня есть "master" UIView (на самом деле UIScrollView, но это единственная прокрутка для каждой страницы). В качестве подвида этого "master" у меня есть "pageView" (подкласс UIScrollView). Этот UIScrollView может иметь любое содержимое (например, UIImageView). У "master" есть еще один подвид: PaintView (подкласс UIView). С помощью этого вида я отслеживаю движения пальцев и рисую их.

Структура выглядит следующим образом:

[master.view addSubview: pageView];
[master.view addSubview: paintView];

Я знаю, когда пользователь увеличивает масштаб (за это отвечает pageView), и при вызовах делегата/метода я меняю кадр paintView в соответствии с изменением масштаба во время действия масштабирования. После масштабирования (scrollViewDidEndZooming:withView:atScale) я вызываю собственный метод перерисовки paintView.

Метод перерисовки и drawRect:

-(void)redrawForScale:(float)scale {
    for (UIBezierPath *path in _pathArray) {
        //TransformMakeScale...
    }
    [self setNeedsDisplay];
} 

-(void)drawRect:(CGRect)rect {
    for (UIBezierPath *path in _pathArray) {
        [path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    } 
}

Проблема: когда я увеличиваю масштаб, я получаю предупреждение о памяти, и приложение аварийно завершает работу.

В профилировщике Allocations я вижу, что приложению принадлежит много памяти, но я не понимаю, почему. Когда я не вызываю 'setNeedDisplay' после моего метода 'redrawForScale', приложение не падает.

Когда я регистрирую прямоугольник в drawRect, я вижу такие значения: {{0, 0,299316}, {4688, 6630}}.


person Sebastian    schedule 26.10.2012    source источник


Ответы (1)


Проблема заключается в том, чтобы (пере)рисовать такой огромный CGRect (поправьте меня, если это неправильно). Решение для меня состоит в том, чтобы избежать вызова пользовательского метода drawRect. В некоторых ответах на stackoverflow (и я думаю, что где-то в документах Appls) упоминалось, что пользовательский drawRect: снизит производительность (поскольку iOS не может творить магию в пользовательском методе drawRect).

Мое решение: использование файла CAShapeLayer. Для каждого UIBezierPath я создаю экземпляр CAShapeLayer, добавляю UIBezierPath к атрибуту path слоя и добавляю слой в качестве подслоя в свое представление.

CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] initWithLayer:self.layer];
shapeLayer.lineWidth = 10.0;
shapeLayer.strokeColor = [UIColor blackColor].CGColor;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.path = myBezierPath.CGPath;
[self.layer addSublayer:shapeLayer];

С этим решением мне не нужно реализовывать drawRect. Таким образом, приложение не будет падать, даже при большом максимальном масштабе масштабирования.

После изменения UIBezierPath (перевод, масштабирование, изменение цвета) мне нужно снова установить измененный bezierPath в shapeLayer (снова установить атрибут path shapeLayer).

person Sebastian    schedule 05.12.2012