的drawRect:/ renderInContext:问题(drawRect:/renderInC

2019-06-23 14:36发布

似乎有一点问题的企图拉拢我认为到上下文。

我的基本设置,我有拥有一个视图控制器UIPageViewController我在其中与可由用户手指上绘制视图负载控制器。 基本上,我有一本书,可以在绘制。

当页面在书打开我通过调用保存图像

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

这则返回值被保存到一个文件。 然而,当我把这个保存方法,然后行

[self.layer renderInContext:UIGraphicsGetCurrentContext()];

被击中,这似乎让我打电话drawRect:方法,该方法如下覆盖,

- (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];
}

这是有道理的,但似乎直到最后,我在这条线得到一个EXC_BAD_ACCESS得到递归调用

[self.currentImage drawAtPoint:CGPointMake(0.0f, 0.0f)];

在我完全丧失,什么是造成这一点,并一直推动我坚果。

如果有帮助,我的调用堆栈开始喜欢这个

然后继续递归,直到最后结尾

会很感激,并帮助和洞察力,任何人都可以给!

编辑:(搬加入触摸)

-(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];    

}

Answer 1:

你不能调用[self.layer renderInContext:]drawRect:期。 正如你已经想通了, renderInContext:调用drawRect:如果实现,这将导致无限递归。

您应该呈现一本书是分开,然后用所呈现的图像,让用户在它上面绘制。 做到这一点的一种方法是在以包围一个自包含的绘图代码UIGraphicsBeginImageContext() / UIGraphicsEndImageContext()块,并使用在所得到的图像drawRect: 另一种方法是使用不是彼此,一个描绘未改变的书的子视图两个不同视图,所述其他描绘用户草图。

编辑:首先,你需要一个原始图像(书页,等等)。 绘制一个内部UIGraphicsBeginImageContext() / UIGraphicsEndImageContext(),而不调用 [self.layer renderInContext:] ,并将其保存在视图的实例变量(比如, self.currentImage )。 在touchesMoved:withEvent:调用setNeedsDisplay (它会调用drawRect:你)更新视图。 使用self.currentImagedrawRect:作为背景图像。

我希望我不是太含糊。



文章来源: drawRect:/renderInContext: issues