CATiledLayer绘图崩溃
在我的应用程序中,我使用具有以下视图层次结构:
UIView
----UIScrollView
--------TiledView (UIView subclass, uses CATiledLayer for drawing)
----OverlayView (UIView subclass)
简而言之 - TiledView
显示大平铺图像 我还将自定义旋转应用于该视图:
tiledView.transform = CGAffineTransformMakeRotation(angle);
TiledView 的绘图方法:
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
...
NSString *fileName = [NSString stringWithFormat:@"tile_%d_%d.jpg", y + 1, x + 1];
UIImage *image = [UIImage imageNamed:fileName];
[image drawInRect:rect];
}
UIScrollView 允许滚动和缩放其内容。
Overlay 视图位于 UIScrollView 之上,具有透明背景并执行一些自定义绘图。我使用单独的视图来确保线宽和字体大小不受滚动视图中缩放比例的影响。
OverlayView 的绘图方法:
- (void)drawRect:(CGRect)rect {
// Drawing code
[super drawRect:rect];
// Custom drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 0, 1);
CGContextSetLineWidth(context, lineWidth);
CGContextBeginPath(context);
CGContextMoveToPoint(context, (int)startPoint.x,(int) startPoint.y);
if (usesMidPoint)
CGContextAddLineToPoint(context, (int)midPoint.x, (int)midPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextStrokePath(context);
}
最初一切正常,但在使用视图(例如来回滚动等)后,它在绘图函数之一的某些随机行上崩溃。作为示例,应用程序在线崩溃:
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 0, 1);
使用堆栈:
#0 0x00503088 in CGColorEqualToColor
#1 0x00505430 in CGGStateSetStrokeColor
#2 0x005053b6 in setStrokeColorWithComponents
#3 0x0056150f in CGContextSetRGBStrokeColor
#4 0x000764ab in -[GADrawView drawRect:] at GADrawView.m:38
#5 0x016a7a78 in -[UIView(CALayerDelegate) drawLayer:inContext:]
#6 0x0077c007 in -[CALayer drawInContext:]
我是否缺少多个图形上下文之间所需的任何同步?或者可能有更好的方法来做我正在尝试的事情?
in my application I use have the following views hierarchy:
UIView
----UIScrollView
--------TiledView (UIView subclass, uses CATiledLayer for drawing)
----OverlayView (UIView subclass)
In short - TiledView
displays large tiled image I also apply custom rotation to that view:
tiledView.transform = CGAffineTransformMakeRotation(angle);
Drawing method for TiledView:
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
...
NSString *fileName = [NSString stringWithFormat:@"tile_%d_%d.jpg", y + 1, x + 1];
UIImage *image = [UIImage imageNamed:fileName];
[image drawInRect:rect];
}
UIScrollView allows both scrolling and zooming of its contents.
Overlay view lays over UIScrollView, has transparent background and performs some custom drawing. I use separate view to make sure that line width and font size are not affected by zoom scale in scroll view.
Drawing method for OverlayView:
- (void)drawRect:(CGRect)rect {
// Drawing code
[super drawRect:rect];
// Custom drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 0, 1);
CGContextSetLineWidth(context, lineWidth);
CGContextBeginPath(context);
CGContextMoveToPoint(context, (int)startPoint.x,(int) startPoint.y);
if (usesMidPoint)
CGContextAddLineToPoint(context, (int)midPoint.x, (int)midPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextStrokePath(context);
}
Initially everything works ok, but after some playing with the view (e.g. scrolling it to and fro etc) it crashes on some random line in one of the drawing functions. As an example app crashes on line:
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 0, 1);
with stack:
#0 0x00503088 in CGColorEqualToColor
#1 0x00505430 in CGGStateSetStrokeColor
#2 0x005053b6 in setStrokeColorWithComponents
#3 0x0056150f in CGContextSetRGBStrokeColor
#4 0x000764ab in -[GADrawView drawRect:] at GADrawView.m:38
#5 0x016a7a78 in -[UIView(CALayerDelegate) drawLayer:inContext:]
#6 0x0077c007 in -[CALayer drawInContext:]
Am I missing any synchronization required between several graphics contexts? Or may be there's better way to do what I'm trying?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
找到了问题的解决方案。如 Apple 的技术说明
CATiledLayer
使用单独的线程来获取其图块的内容:因此,解决方案是将所有绘图代码从
-drawRect:
方法移至-drawLayer:inContext:
并仅使用 Core Graphics 函数进行绘制。使用 CoreGraphics 绘图还需要在坐标系之间进行一些转换 - 苹果论坛的这篇帖子提供了帮助与它们(请参阅drawLayer:
方法实现)。所以
TiledView
的正确绘制代码:Found solution to the problem. As described in Apple's technical note
CATiledLayer
uses separate thread to fetch the contents for its tiles:So the solution is to move all drawing code from
-drawRect:
method to-drawLayer:inContext:
and draw using only Core Graphics functions. Drawing with CoreGraphics also requires some transformations between coordinates systems - this post from apple forums helped with them (seedrawLayer:
method implementation).So the correct drawing code for
TiledView
: