我将CATiledLayer用作UIView的衬里,并将其放入UIScrollView中。在我的视图的init方法中,我正在创建CGPathRef对象,该对象绘制了简单的线条。当我尝试在drawLayer:inContext中绘制此路径时,在我滚动/缩放时,它偶尔会因EXEC_BAD_ACCESS而崩溃。
代码非常简单,我仅使用标准CG *函数:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
tiledLayer.levelsOfDetail = 10;
tiledLayer.levelsOfDetailBias = 5;
tiledLayer.tileSize = CGSizeMake(512.0, 512.0);
CGMutablePathRef mutablePath = CGPathCreateMutable();
CGPathMoveToPoint(mutablePath, nil, 0, 0);
CGPathAddLineToPoint(mutablePath, nil, 700, 700);
path = CGPathCreateCopy(mutablePath);
CGPathRelease(mutablePath);
}
return self;
}
+ (Class) layerClass {
return [CATiledLayer class];
}
- (void) drawRect:(CGRect)rect {
}
- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
CGContextFillRect(ctx, self.bounds);
CGContextSetLineWidth(ctx, 5);
CGContextAddPath(ctx, path);
CGContextDrawPath(ctx, kCGPathStroke);
}
- (void)dealloc {
[super dealloc];
}
更新:
我注意到这个问题仅在iOS 5上存在,在4.3上运行良好
最佳答案
尝试在自定义MKOverlayView上绘制缓存的CGPath对象时遇到了类似的问题。
崩溃可能是因为无法同时在多个线程上绘制CGPath-这是一个不透明的类(如文档中所指定),该类在其点数组中包含指向当前点的指针。在绘制数组时,同时有两个或多个线程在此数组上进行迭代可能导致未定义的行为和崩溃。
我通过将CGPath对象复制到每个绘图线程(包含在互斥锁中以防止不完全复制)来解决此问题:
//lock the object's cached data
pthread_mutex_lock(&cachedPathMutex);
//get a handle on the previously-generated CGPath (myObject exists on the main thread)
CGPathRef myPath = CGPathCreateCopy(myObject.cachedPath);
//unlock the mutex once the copy finishes
pthread_mutex_unlock(&cachedPathMutex);
// all drawing code here
CGContextAddPath(context, myPath);
...
...
CGPathRelease(myPath);
如果您担心在每个线程上执行复制的内存开销,则也可以直接在缓存的CGPath对象上工作,但是互斥锁在整个绘制过程中必须保持锁定状态(这会破坏线程化的目的)画画):
//lock the object's cached data
pthread_mutex_lock(&cachedPathMutex);
//get a handle on the previously-generated CGPath (myObject exists on the main thread)
CGPathRef myPath = myObject.cachedPath;
// draw the path in the current context
CGContextAddPath(context, myPath);
...
...
//and unlock the mutex
pthread_mutex_unlock(&cachedPathMutex);
我将通过说我不是Quartz的多线程绘图方面的专家来限定我的回答,只是这种方法解决了我的情况下的崩溃。祝好运!
更新:
我现在重新审查了这段代码,因为iOS 5.1.0已经发布,并且看起来该问题的根本原因实际上可能是iOS 5.0.x中Quartz中的错误。在CGPathCreateCopy()和互斥锁删除的iOS 5.1.0上进行测试时,我发现iOS 5.0.x上没有发生任何崩溃。
//get a handle on the previously-generated CGPath (myObject exists on the main thread)
CGPathRef myPath = myObject.cachedPath;
// all drawing code here
CGContextAddPath(context, myPath);
...
...
//drawing finished
由于有可能我们会在一段时间内支持iOS 5.0.x,因此将互斥锁保留在您的代码中(不会对性能造成轻微影响),或者只是在绘制之前运行版本检查都不会造成损害。
关于iphone - 绘制先前准备的CGPath时,CATiledLayer崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8533656/