renderincontext内存泄漏,如果不在主线程上使用

时间:2012-10-11 15:59:48

标签: objective-c ios uiimage core-graphics

我正在尝试使用下面的代码将我的UIView转换为UIImage。

+ (UIImage *) imageWithView:(UIView *)view{
     float scale = 1.0f;
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, scale);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage* img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    view.layer.contents = nil;
    return img;
}

此代码存在两个问题。

1。当我在后台线程(!mainThread)

中运行此代码时

在后台线程中调用renderInContext时遇到内存泄漏问题。

2。当我在主线程

上运行此代码时

没有内存泄漏但是在iPad 3上我从UIView创建图像时遇到了一些性能问题(当调用此方法时我的UI挂起)。因为我需要在几秒钟内调用此函数超过5次,因此UI挂起会给用户带来非常糟糕的体验。

如果我在这里做错了,请指导我吗?

2 个答案:

答案 0 :(得分:8)

我认为问题1与UIKit不是线程安全的事实有关,并且它的使用会导致各种副作用。

如果您遇到性能问题,我看到的唯一前进方法是直接在辅助线程上使用CoreGraphics(不是UIKit)。

你可以尝试这样的事情作为开始:

size_t width = view.bounds.size.width;
size_t height = view.bounds.size.height;

unsigned char *imageBuffer = (unsigned char *)malloc(width*height*4);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef imageContext =
    CGBitmapContextCreate(imageBuffer, width, height, 8, width*4, colourSpace,
              kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);

CGColorSpaceRelease(colourSpace);

[view.layer renderInContext:imageContext];

CGImageRef outputImage = CGBitmapContextCreateImage(imageContext);

CGImageRelease(outputImage);
CGContextRelease(imageContext);
free(imageBuffer);

如您所见,这比UIKit方式复杂得多,但它可以在辅助线程上运行(假设您找到了将outputImage传递回UI线程的方法,没有显示。)

答案 1 :(得分:1)

我刚刚在线程上发生了这种情况(renderInContext导致的内存泄漏)。我循环了数百个屏幕外视图,将它们呈现给UIImage个对象,并将它们保存为PNG文件。为我解决问题的是将我的循环内容包裹在@autoreleasepool块中:

<强>断裂:

for (...) {
   ...render layer in context...
   ...save image to disk...
}

<强>使用:

for (...) {
   @autoreleasepool {
      ...render layer in context...
      ...save image to disk...
   }
}

有道理,对吧?