Objective c CGContextDrawImage-EXC_BAD_访问和地图覆盖渲染器

Objective c CGContextDrawImage-EXC_BAD_访问和地图覆盖渲染器,objective-c,exc-bad-access,Objective C,Exc Bad Access,我有一张地图。有时,我在CGContextDrawImage 我的图像设置器设置覆盖图像的方法 -(void)SetImageRef:(CGImageRef)imageRef { CGImageRelease(_imageReference); _imageReference = CGImageCreateCopy(imageRef); } 我的画法 - (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZ

我有一张地图。有时,我在
CGContextDrawImage

我的图像设置器设置覆盖图像的方法

-(void)SetImageRef:(CGImageRef)imageRef
{       
    CGImageRelease(_imageReference);
    _imageReference = CGImageCreateCopy(imageRef);    
}
我的画法

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
    MKMapRect theMapRect = self.overlay.boundingMapRect;
    CGRect theRect = [self rectForMapRect:theMapRect];

    CGContextSetInterpolationQuality(context, self.interpolation);

    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextTranslateCTM(context, 0.0, -theRect.size.height);
    CGContextDrawImage(context, theRect, _imageReference); //<---- EXC_BAD_ACCESS

}
-(void)drawMapRect:(mkmapret)mapret zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
MKMapRect theMapRect=self.overlay.boundingMapRect;
cRect theRect=[自校正:TheMarect];
CGContextSetInterpolationQuality(上下文,self.interpolation);
CGContextScaleCTM(上下文,1.0,-1.0);
CgContextTranslateCm(上下文,0.0,-theRect.size.height);

CGContextDrawImage(上下文、上下文、图像引用);//我怀疑您有时会将当前的
\u imageReference
传递给
SetImageRef:
。您的
SetImageRef
实现无法安全地处理这种情况。当您使用
CGImageRelease
释放
\u imageReference
时,它将被释放(除非有其他东西在保留
\u imageReference
,但听起来好像不是这样)。如果您使用以下工具进行复制:

_imageReference = CGImageCreateCopy(imageRef);
碰巧,
imageRef==\u imageReference
然后会发生什么?你最终得到的是一个僵尸(或即将成为僵尸)图像的副本。现在,你正在制作一个副本,所以你可能会认为,
imageRef
是否死亡无关紧要(只要它在发布后没有立即被覆盖,尽管这仍然是不安全的代码),但有一个陷阱。
CGImageCreateCopy
的文档说明:

仅复制图像结构本身;复制 基础数据不可用

因此,
\u imageReference
的“图像结构”数据可能是安全的,但是
\u imageReference
实际生成像素所需的数据是不安全的。这就是为什么最终尝试使用
CGContextDrawImage
渲染图像时会出现问题的原因

这是一种非常冗长的说法,表示您需要对
SetImageRef
更加小心。我建议您在
imageRef==\u imageReference
的特殊情况下尽早返回:

-(void)SetImageRef:(CGImageRef)imageRef {
    if (imageRef == _imageReference) {
        return;
    }

    CGImageRelease(_imageReference);
    _imageReference = CGImageCreateCopy(imageRef);    
}

我为OS X开发了颜色选择器,在使用两个物理显示器时遇到了相同的问题。请尝试将您的自定义“setImageRef”写为:


Aaron Golden对此问题有更详细的描述。

这不是问题所在Aaron,这解决了我的问题,但出现了相同的错误。感谢您发布。@MartinPerry如果这不是问题所在,您是否以其他方式解决了它?如果您这样做,您应该将其发布在此处。
//Fix CGContextDrawImage Crash
-(void)SetImageRef:(CGImageRef)imgRef
{
    if (imgRef == _imageRef) return;
    CGImageRelease(_imageRef);
    _imageRef = CGImageCreateCopy(imgRef);
}