drawRect:/ renderInContext:问题 [英] drawRect:/renderInContext: issues

查看:41
本文介绍了drawRect:/ renderInContext:问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图将我的视图绘制到上下文中似乎有点问题。



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



当翻页时,我通过调用


$ b保存图像$ b

 -(UIImage *)wholeImage {
//将图层渲染为图像并返回
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * wholePageImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
返回WholePageImage;
}

然后将其返回值保存到文件中。但是,当我调用此保存方法时,则行

  [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 

受到打击,这似乎在调用我的 drawRect:方法,如下所示,

 -(void)drawRect:(CGRect)rect {
//绘制图像的当前状态
[self.currentImage drawAtPoint:CGPointMake(0.0f,0.0f)];
CGPoint midPoint1 = [self midPointOfPoint1:previousPoint1 point2:previousPoint2];
CGPoint midPoint2 = [self midPointOfPoint1:currentPoint point2:previousPoint1];

//获取上下文
CGContextRef context = UIGraphicsGetCurrentContext();

//将新的一行添加到图像
[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);

//调用super
[super drawRect:rect];
}

这很有意义,但似乎被递归调用,直到最终我得到一个EXC_BAD_ACCESS

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

Am对造成这种情况的原因完全感到困惑,并一直让我发疯。



如果有帮助,我的调用堆栈就这样开始





,然后递归进行直到最终以


结尾



将非常感谢任何人都可以给予的帮助和见识!



编辑:(已添加触摸功能)

 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
//获取触摸
UITouch * touch = [触摸anyObject ];

//获取积分
previousPoint2 = previousPoint1;
previousPoint1 = [触摸previousLocationInView:self];
currentPoint = [touch locationInView:self];

//计算中点
CGPoint mid1 = [self midPointOfPoint1:previousPoint1 point2:previousPoint2];
CGPoint mid2 = [self midPointOfPoint1:currentPoint point2:previousPoint1];

//为最后几个点创建路径
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,NULL,mid1.x,mid1.y);
CGPathAddQuadCurveToPoint(路径,NULL,previousPoint1.x,previousPoint1.y,mid2.x,mid2.y);
CGRect pathBounds = CGPathGetBoundingBox(path);
CGPathRelease(path);

//考虑线宽
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];

}

解决方案

您不得在 drawRect:期间调用 [self.layer renderInContext:] 。如您所知, renderInContext:如果实现了,则会调用 drawRect:,这将导致无限递归。 / p>

您应该单独渲染一本书,然后使用渲染的图像让用户在其上绘画。一种方法是在 UIGraphicsBeginImageContext() / UIGraphicsEndImageContext()块中包含一个独立的绘图代码并在 drawRect:中使用生成的图像。另一种方法是使用两个彼此都不是子视图的不同视图,一个是未更改的书,另一个是用户的草图。



编辑:首先,您需要原始图像(书籍页面等)。将其绘制在 UIGraphicsBeginImageContext() / UIGraphicsEndImageContext()中而无需调用 [self.layer renderInContext:] 并将其保存在视图的ivar中(例如, self.currentImage )。在 touchesMoved:withEvent:中调用 setNeedsDisplay (它将调用 drawRect:给您)以更新视图。在 drawRect:中使用 self.currentImage 作为背景图像。



我希望我不太模糊。


Seem to be having a bit of an issue trying to draw my view into a context.

My basic setup is, I have a view controller that owns a UIPageViewController in which I load controllers with views that can be drawn on by the users finger. Basically I have a book that can be drawn in.

When the page is turned in the book I save the image by calling

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

The return value of this then gets saved to a file. However when I call this save method then line

[self.layer renderInContext:UIGraphicsGetCurrentContext()];

gets hit, which seems to make a call to my drawRect: method, which is overridden as follows,

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

which makes sense, but it seems to get called recursively until eventually I get an EXC_BAD_ACCESS on this line

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

Am at a complete loss as to what is causing this and has been driving me nuts.

If it helps, my call stack starts like this

and then goes on recursively until it finally ends with

Would really appreciate and help and insight that anyone can give!!

EDIT: (Touches moved added)

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

}

解决方案

You must not call [self.layer renderInContext:] in drawRect:, period. As you have figured out, renderInContext: calls drawRect: if it is implemented, which will cause an infinite recursion.

You should render a book as is separately, then use the rendered image to let users draw on top of it. One way to do that is to enclose a self-contained drawing code in the UIGraphicsBeginImageContext()/UIGraphicsEndImageContext() block and use the resulting image in drawRect:. Another way is to use two different views which are not subviews of each other, one drawing an unaltered book, the other drawing user sketches.

EDIT: first of all, you need an original image (book page, whatever). Draw it inside a UIGraphicsBeginImageContext()/UIGraphicsEndImageContext() block without calling [self.layer renderInContext:] and save it in the view's ivar (say, self.currentImage). In touchesMoved:withEvent: call setNeedsDisplay (it will call drawRect: for you) to update the view. Use self.currentImage in drawRect: as the background image.

I hope I'm not too vague.

这篇关于drawRect:/ renderInContext:问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆