Iphone CATiledLayer绘图崩溃

Iphone CATiledLayer绘图崩溃,iphone,uiview,crash,drawing,catiledlayer,Iphone,Uiview,Crash,Drawing,Catiledlayer,在我的应用程序中,我使用以下视图层次结构: UIView ----UIScrollView --------TiledView (UIView subclass, uses CATiledLayer for drawing) ----OverlayView (UIView subclass) 简而言之-平铺视图显示大平铺图像我还对该视图应用自定义旋转: tiledView.transform = CGAffineTransformMakeRotation(angle); 平铺视图的绘制方法:

在我的应用程序中,我使用以下视图层次结构:

UIView
----UIScrollView
--------TiledView (UIView subclass, uses CATiledLayer for drawing)
----OverlayView (UIView subclass)
简而言之-
平铺视图
显示大平铺图像我还对该视图应用自定义旋转:

tiledView.transform = CGAffineTransformMakeRotation(angle);
平铺视图的绘制方法:

- (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,具有透明背景,并执行一些自定义绘图。我使用单独的视图来确保行宽度和字体大小不受滚动视图中缩放比例的影响

覆盖视图的绘制方法:

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

我是否缺少几个图形上下文之间所需的任何同步?或者可能有更好的方法来做我正在尝试的事情?

找到了问题的解决方案。正如Apple的
CATiledLayer
中所述,它使用单独的线程获取其分幅的内容:

CATiledLayer实现其 使用背景线程绘制 要获取每个磁贴的内容, 但是,提供了绘图功能 UIKit依赖于全球环境 堆栈,并且在使用CATiledLayer时也是如此 使用任何UIKit开始渲染 绘图函数可能导致竞争 条件

因此,解决方案是将所有绘图代码从
-drawRect:
方法移动到
-drawLayer:inContext:
,并仅使用核心图形功能进行绘图。使用CoreGraphics绘图还需要在坐标系之间进行一些转换——这在苹果论坛上有帮助(请参见
drawLayer:
method implementation)

因此,
平铺视图的正确图形代码是:

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

找到了问题的解决办法。正如Apple的
CATiledLayer
中所述,它使用单独的线程获取其分幅的内容:

CATiledLayer实现其 使用背景线程绘制 要获取每个磁贴的内容, 但是,提供了绘图功能 UIKit依赖于全球环境 堆栈,并且在使用CATiledLayer时也是如此 使用任何UIKit开始渲染 绘图函数可能导致竞争 条件

因此,解决方案是将所有绘图代码从
-drawRect:
方法移动到
-drawLayer:inContext:
,并仅使用核心图形功能进行绘图。使用CoreGraphics绘图还需要在坐标系之间进行一些转换——这在苹果论坛上有帮助(请参见
drawLayer:
method implementation)

因此,
平铺视图的正确图形代码是:

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

您能详细说明一下如何将平铺视图本身挂接到滚动视图上吗?感谢您将其添加为子视图,并将scroll view的contentsSize设置为适当的值。显然,从iOS 4.0开始,这不再是必需的-根据已接受答案中链接的技术说明。在drawRect中绘图:现在允许,无需通过坐标变换跳转。请详细说明如何将平铺视图本身挂接到滚动视图上?感谢您将其添加为子视图,并将scroll view的contentsSize设置为适当的值。显然,从iOS 4.0开始,这不再是必需的-根据已接受答案中链接的技术说明。在drawRect中绘图:现在允许,无需通过坐标变换跳过环。