我正在尝试使用下面的代码将我的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挂起会给用户带来非常糟糕的体验。
如果我在这里做错了,请指导我吗?
答案 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...
}
}
有道理,对吧?