简体   繁体   English

目标C:生成UIImage时为EXC_BAD_ACCESS

[英]Objective C: EXC_BAD_ACCESS when generating a UIImage

I have a view that generates an image based on a series of layers. 我有一个基于一系列图层生成图像的视图。 I have images for the background, for the thumbnail, and finally for an overlay. 我有用于背景,缩略图和最后用于覆盖的图像。 Together, it makes one cohesive display. 一起,它使一个内聚的显示。

It seems to work a dream, except for when it doesn't. 似乎在做梦,除非不是。 For seemingly no reason, I get an EXC_BAD_ACCESS on the specified line below after it's generated somewhere between 8 and 20 images. 似乎没有原因,在生成指定的8到20张图像之后,我在下面的指定行上得到了EXC_BAD_ACCESS。 I've run it through the memory leak tool and allocation tool, and it's not eating up tons of memory and it's not leaking. 我已经通过内存泄漏工具和分配工具运行了它,它没有耗尽大量内存,也没有泄漏。 I'm totally stumped. 我完全迷住了。

Here's the relevant code: 以下是相关代码:

- (UIImage *)addLayer:(UIImage *)layer toImage:(UIImage *)background atPoint:(CGPoint)point {
  CGSize size = CGSizeMake(240, 240);
  UIGraphicsBeginImageContext(size);

  [background drawAtPoint:CGPointMake(0, 0)];  // <--- error here
  [layer drawAtPoint:point];

  UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return result;
}


// Build the layered image -- thingPage onto thingBackground,
// then the screenshot on that, then the thingTop on top of it all.
// thingBackground, thingPage and thingTop are all preloaded UIImages.
-(UIImage *)getImageForThing:(Thing *)t {
  [self loadImageCacheIfNecessary];

  if (!t.screenshot) {
    return [UIImage imageNamed:@"NoPreview.png"];
  } else {
    UIImage *screenshot = t.screenshot;
    UIImage *currentImage = [self addLayer:thingPage toImage:thingBackground atPoint:CGPointMake(0, 0)];
    currentImage = [self addLayer:screenshot toImage:currentImage atPoint:CGPointMake(39, 59)];
    currentImage = [self addLayer:thingTop toImage:currentImage atPoint:CGPointMake(0, 1)]; 

    return currentImage;
  }
}

I can't find anywhere that this is going wrong, and I've been tearing my hair out for a couple of hours on this. 我找不到任何地方出了问题,为此,我已经把头发扯了几个小时。 It's the final known bug in the system, so you can imagine how antsy I am to fix it! 这是系统中最后一个已知的错误,因此您可以想象我要修复它的热情! :-) :-)

Thanks in advance for any help. 在此先感谢您的帮助。

As to me, I always use -(void)drawInRect: instead of -(void)drawAtPoint: 对于我来说,我总是使用-(void)drawInRect:而不是-(void)drawAtPoint:


CGRect rtDraw;
rtDraw.origin = CGPointZero;
rtDraw.size = size;
[background drawInRect:rtDraw];
[layer drawInRect:rtDraw];

And .... The paint method with UIGraphicsBeginImageContext(size) and UIGraphicsEndImageContext() is not thread-safe. 并且....具有UIGraphicsBeginImageContext(size)和UIGraphicsEndImageContext()的paint方法不是线程安全的。 Those functions will push or pop a context with stack struct, which is managed by system. 这些功能将通过系统管理的栈结构推送或弹出上下文。

EXC_BAD_ACCESS is almost always due to accessing an object that has already been released. EXC_BAD_ACCESS几乎总是归因于访问已释放的对象。 In your code this seems to be t.screenshot . 在您的代码中,这似乎是t.screenshot Check creation (and retaining if it is an instance variable) of the object returned by Thing 's screenshot property. 检查Thingscreenshot属性返回的对象的创建(并保留是否为实例变量)。

As it turns out, the error wasn't in the code I posted, it was in my caching of the thingBackground , thingPage and thingTop images. 事实证明,该错误不是在我发布的代码中,而是在我对thingBackgroundthingPagethingTop图像进行缓存时。 I wasn't retaining them. 我没有保留他们。 Here's the missing code, fixed: 这是固定的缺少的代码:

-(void)loadImageCacheIfNecessary {
  if (!folderBackground) {
    thingBackground = [[UIImage imageNamed:@"ThingBack.png"] retain];
  }
  if (!folderPage) {
    thingPage = [[UIImage imageNamed:@"ThingPage.png"] retain];
  }
  if (!folderTop) {
    thingTop = [[UIImage imageNamed:@"ThingTop.png"] retain];
  }
}

I will admit I'm still not comfortable with the whole retain/release/autorelease stuff in Objective C. Hopefully it'll sink in one day soon. 我承认我对Objective C中的全部保留/释放/自动释放内容仍然不满意。希望它很快就会消失。 :-) :-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM