我有MapOverlayRenderer。有时,我在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
}
什么可能是错的,或者我该如何调试它。
如果我启用了Zombie Objects,崩溃就会消失,但调试控制台中也没有显示任何信息,所以我什么都不知道。
答案 0 :(得分:3)
我怀疑您有时会将当前 _imageReference
传递给SetImageRef:
。您SetImageRef
的实施并不能安全地处理这种情况。当您使用_imageReference
发布CGImageRelease
时,它将被取消分配(除非其他内容保留_imageReference
,但听起来并非如此)。如果您随后复制:
_imageReference = CGImageCreateCopy(imageRef);
然后发生imageRef == _imageReference
然后会发生什么?您最终得到_imageReference
作为僵尸(或即将成为僵尸)图像的副本。现在,你正在复制,所以你可能认为imageRef
正在死亡无关紧要(只要它在发布后没有被立即覆盖,尽管这仍然是不安全的代码),但有一个问题。 CGImageCreateCopy
笔记的文档:
仅复制图像结构本身;该 基础数据不是。
因此_imageReference
的“图像结构”数据可能是安全的,但_imageReference
实际生成像素所需的数据不安全。这就是为什么当你最终尝试使用CGContextDrawImage
渲染图像时会遇到问题。
这是一个非常长篇大论的说法,你需要让SetImageRef
更加小心。我建议您在imageRef == _imageReference
:
-(void)SetImageRef:(CGImageRef)imageRef {
if (imageRef == _imageReference) {
return;
}
CGImageRelease(_imageReference);
_imageReference = CGImageCreateCopy(imageRef);
}
答案 1 :(得分:0)
我为OS X开发了Color Picker,当我使用两个物理显示器时也遇到了同样的问题。试着写你的自定义&#34; setImageRef&#34;为:
//Fix CGContextDrawImage Crash
-(void)SetImageRef:(CGImageRef)imgRef
{
if (imgRef == _imageRef) return;
CGImageRelease(_imageRef);
_imageRef = CGImageCreateCopy(imgRef);
}
Aaron Golden对此问题有更详细的描述。