I have a method which is called in a loop, that looks something like th开发者_运维问答is:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImageView *background = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, PAGE_WIDTH, PAGE_HEIGHT)];
background.image = backgroundImg;
for (UIView *view in viewArray)
{
[background addSubview:view];
}
UIGraphicsBeginImageContext(background.frame.size);
[background.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
for (UIView *view in background.subviews)
[view removeFromSuperview];
background.image = nil;
[background release];
[image retain];
[pool drain];
[image autorelease];
return image;
However, according to Instruments Memory Monitor, the memory usage goes up and up, and never comes down until the end of the loop. (It crashes.)
If I replace the UIGraphicsBeginImageContext to UIGraphicsEndImageContext with
UIImage *image = someotherimage;
then the memory does not spike, but is allocated and reduces on every iteration of the loop, as I would expect, due to the Autorelease pool. (It doesn't crash)
And if I just comment out the renderInContext line it works fine. (Doesn't crash)
So it looks as if renderInContext is holding onto the image somehow - how can I get it to release it? Or any alternative suggestions please :)?
Naturally after 3 days of experimenting, I find the answer (an answer, anyway, and I would be glad of comments on this) within the hour.
I add
background.layer.contents = nil;
after
UIGraphicsEndImageContext();
and the cached memory in the layer is uncached :).
I am not using a UIImageView, so setting layer.contents = nil
did not work for me. However, I found a different solution that, while not ideal, does work. It appears that the memory allocated by renderInContext
does not get freed until the main_queue is idle. So, I did the following:
dispatch_queue_t queue = dispatch_queue_create("com.example.imageprocessing", DISPATCH_QUEUE_SERIAL);
for (int k = 0; k < images.count; ++k) {
dispatch_async(queue, ^{
dispatch_sync(dispatch_get_main_queue(), ^{
@autoreleasepool {
...
UIGraphicsBeginImageContext(self.view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
...
}
}
}
}
This solved my memory issue. I'm not processing a lot of images, so I don't know how the performance is affected.
精彩评论