Вопрос по calayer, uiview, drawrect, ios, exc-bad-access – drawRect: / renderInContext: проблемы

0

Кажется, у меня возникли некоторые проблемы, пытаясь привлечь мое мнение в контекст.

Моя основная настройка, у меня есть контроллер представления, который владеетUIPageViewController в котором я загружаю контроллеры с представлениями, которые могут быть нарисованы пальцем пользователя. По сути, у меня есть книга, которую можно нарисовать.

Когда страница переворачивается в книге, я сохраняю изображение, вызывая

<code>- (UIImage *)wholeImage {
    // Render the layer into an image and return
    UIGraphicsBeginImageContext(self.bounds.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *wholePageImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return wholePageImage;
}
</code>

Возвращаемое значение затем сохраняется в файл. Однако, когда я вызываю этот метод сохранения, то строка

<code>[self.layer renderInContext:UIGraphicsGetCurrentContext()];
</code>

получает удар, который, кажется, звонит моемуdrawRect: метод, который переопределяется следующим образом,

<code>- (void)drawRect:(CGRect)rect {
    // Draw the current state of the image
    [self.currentImage drawAtPoint:CGPointMake(0.0f, 0.0f)];
    CGPoint midPoint1 = [self midPointOfPoint1:previousPoint1 point2:previousPoint2];
    CGPoint midPoint2 = [self midPointOfPoint1:currentPoint point2:previousPoint1];

    // Get the context
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Add the new bit of line to the image
    [self.layer renderInContext:context];
    CGContextMoveToPoint(context, midPoint1.x, midPoint1.y);
    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, midPoint2.x, midPoint2.y); 
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineWidth(context, self.lineWidth);
    if (self.drawMode == LNDrawViewDrawModeTipex) CGContextSetBlendMode(context, kCGBlendModeClear);
    else CGContextSetBlendMode(context, kCGBlendModeCopy);
    CGContextSetStrokeColorWithColor(context, self.lineColour.CGColor);
    CGContextStrokePath(context);

    // Call super
    [super drawRect:rect];
}
</code>

это имеет смысл, но, кажется, вызывается рекурсивно, пока в конце концов я не получу EXC_BAD_ACCESS в этой строке

<code>[self.currentImage drawAtPoint:CGPointMake(0.0f, 0.0f)];
</code>

Я в полной растерянности относительно того, что вызывает это и сводит меня с ума.

Если это поможет, мой стек вызовов начинается следующим образом

enter image description here

и затем продолжается рекурсивно, пока, наконец, не заканчивается

enter image description here

Был бы очень признателен и помочь и понимание, что каждый может дать !!

РЕДАКТИРОВАТЬ: (штрихи добавлены)

<code>-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    // Get the touch
    UITouch *touch = [touches anyObject];

    // Get the points
    previousPoint2 = previousPoint1;
    previousPoint1 = [touch previousLocationInView:self];
    currentPoint = [touch locationInView:self];

    // Calculate mid point
    CGPoint mid1 = [self midPointOfPoint1:previousPoint1 point2:previousPoint2]; 
    CGPoint mid2 = [self midPointOfPoint1:currentPoint point2:previousPoint1];

    // Create a path for the last few points
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
    CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
    CGRect pathBounds = CGPathGetBoundingBox(path);
    CGPathRelease(path);

    // Take account of line width
    pathBounds.origin.x -= self.lineWidth * 2.0f;
    pathBounds.origin.y -= self.lineWidth * 2.0f;
    pathBounds.size.width += self.lineWidth * 4.0f;
    pathBounds.size.height += self.lineWidth * 4.0f;

    UIGraphicsBeginImageContext(pathBounds.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    self.currentImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self setNeedsDisplayInRect:pathBounds];    
</code>

}

Ваш Ответ

1   ответ
0

[self.layer renderInContext:] вdrawRect:, период. Как вы уже поняли,renderInContext: звонкиdrawRect: если он реализован, то это приведет к бесконечной рекурсии.

Вы должны представить книгу как есть отдельно, а затем использовать изображение, чтобы пользователи могли рисовать поверх него. Один из способов сделать это заключается в том, чтобы заключить вUIGraphicsBeginImageContext()/UIGraphicsEndImageContext() заблокировать и использовать полученное изображение вdrawRect:, Другой способ - использовать два разных вида, которые не являются подпредставлениями друг друга: один рисует неизмененную книгу, другой - пользовательские эскизы.

РЕДАКТИРОВАТЬ: прежде всего, вам нужно оригинальное изображение (страница книги, что угодно). Нарисуйте это внутриUIGraphicsBeginImageContext()/UIGraphicsEndImageContext() блокwithout calling [self.layer renderInContext:] и сохраните его в представлении ivar (скажем,self.currentImage). ВtouchesMoved:withEvent: вызовsetNeedsDisplay (это позвонитdrawRect: для вас), чтобы обновить вид. использованиеself.currentImage вdrawRect: в качестве фонового изображения.

Надеюсь, я не слишком расплывчатый.

Кажется, что drawRect не всегда вызывается из renderInContext, так как мне кажется, что я могу без проблем рисовать на своем виде ...!? Я очень смущен. George Green
Я также обновил свой ответ.
Я думаю, что вы немного ошиблись в своей архитектуре. По сути, вам нужно сделать две несвязанные вещи: нарисовать изображение и нарисовать что-нибудь поверх него. Поскольку они независимы, представление, которое рисует конечный результат, должно брать исходное / фоновое изображение где-то еще, а не из своего собственного содержимого. РезультатdrawRect: устанавливается в качестве слоя представленияcontents. renderInContext: может или не может позвонитьdrawRect: каждый раз, в зависимости от множества факторов вне вашего контроля. Может использовать кэшированное изображение, но это деталь реализации.
Понимаю. Вы также можете визуализировать пользовательский рисунок в изображение, а затем нарисовать изображение вdrawRect:, При рисовании на изображении вы можете использовать результат предыдущего рисования в качестве фона, накапливая операции рисования.drawRect: в этом случае просто всегда будет рисовать окончательное изображение.
Привет, спасибо за ваш ответ. Не думаю, что я полностью уверен, что вы имеете в виду. Только что добавили мои штрихи переместили код на вопрос. Я делаю некоторый код рисования в блоке UIGraphicsBeginImageContext () / UIGraphicsEndImageContext (), но если я не вызову renderInContext снова в drawRect, мне кажется, что я получаю довольно странное поведение ..? George Green

Похожие вопросы