代码之家  ›  专栏  ›  技术社区  ›  Tim Sullivan

目标C:生成uiimage时排除错误访问

  •  0
  • Tim Sullivan  · 技术社区  · 14 年前

    我有一个基于一系列图层生成图像的视图。我有图像作为背景,缩略图,最后是覆盖。它一起构成了一个连贯的显示。

    这似乎是一个梦想,除非它没有实现。似乎没有任何原因,在下面的指定行中生成了8到20个图像之后,我就可以获得一个exc-bad-u访问权限。我通过内存泄漏工具和分配工具运行它,它不会占用大量的内存,也不会泄漏。我受够了。

    相关代码如下:

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

    我找不到哪里出了问题,我已经花了几个小时把头发扯下来了。这是系统中最后一个已知的bug,所以你可以想象我修复它有多不安!-)

    事先谢谢你的帮助。

    3 回复  |  直到 14 年前
        1
  •  0
  •   AechoLiu    14 年前

    至于我,我总是用(空)支取:而不是(空)支取点:

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

    还有… 带有uigraphicsBeginImageContext(大小)和uigraphicsEndImageContext()的绘制方法不是线程安全的。 这些函数将推送或弹出由系统管理的具有堆栈结构的上下文。

        2
  •  0
  •   Nikolai Ruhe    14 年前

    EXC_BAD_ACCESS 几乎总是由于访问已释放的对象。在你的代码中,这似乎是 t.screenshot . 检查由返回的对象的创建(如果是实例变量则保留) Thing screenshot 财产。

        3
  •  0
  •   Tim Sullivan    14 年前

    事实证明,错误不在我发布的代码中,而是在我的缓存中 thingBackground , thingPage thingTop 图像。我没有留住他们。这是丢失的代码,已修复:

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

    我承认我对目标C中的全部保留/释放/自动释放的内容仍然不满意。希望它能在一天内消失。-)