在我的应用程序中,我使用的视图层次结构如下:
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允许滚动和缩放其内容。
覆盖视图覆盖在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:]我是否错过了几个图形上下文之间所需的任何同步?或者有没有更好的方法来做我正在尝试的事情?
发布于 2010-02-22 16:44:23
找到了问题的解决方案。正如在苹果的technical note中所描述的,CATiledLayer使用单独的线程来获取其磁贴的内容:
CATiledLayer通过使用后台线程获取每个分片的内容来实现其绘制,但是UIKit提供的绘制函数依赖于全局上下文栈,因此当CATiledLayer开始渲染时,使用UIKit的任何绘制函数都可能导致竞争条件。
因此,解决方案是将所有绘图代码从-drawRect:方法迁移到-drawLayer:inContext:,并仅使用核心图形函数进行绘图。使用CoreGraphics绘图还需要在坐标系之间进行一些转换-来自苹果论坛的这个post对此很有帮助(请参阅drawLayer:方法实现)。
所以正确的TiledView绘图代码
- (void)drawRect:(CGRect)rect {
//Still need to have this method implemented even if its empty!
}
-(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx
{
// Do all your drawing here. Do not use UIGraphics to do any drawing, use Core Graphics instead.
// convert the CA coordinate system to the iPhone coordinate system
CGContextTranslateCTM(ctx, 0.0f, 0.0f);
CGContextScaleCTM(ctx, 1.0f, -1.0f);
CGRect box = CGContextGetClipBoundingBox(ctx);
// invert the Y-coord to translate between CA coords and iPhone coords
CGPoint pixelTopLeft = CGPointApplyAffineTransform(box.origin, CGAffineTransformMakeScale(1.0f, -1.0f));
NSString *tileUrlString = [self urlForPoint:pixelTopLeft];
UIImage *image = [UIImage imageNamed:tileUrlString];
CGContextDrawImage(ctx, box, [image CGImage]);
}https://stackoverflow.com/questions/2295151
复制相似问题