Bad Access in Background thread drawing
-
14-07-2021 - |
Domanda
What I'm trying to Accomplish
- Draw an image in a background thread
- Convert the
CGImage
to aUIImage
and add it to aUIImageView
on the main thread. - Fade in the imageview, which is on a subclassed
UICollectionViewCell
from alpha value 0 to 1. - Do it all so theres no choppiness when scrolling the
UICollectionView
The Problem
The behavior, at first, acts normally, but quickly digressed into unpredictableness, and usually and quickly resulted in EXC_BAD_ACCESS
errors, happening somewhere in the process of converting uiimage to cgimage or vice versa.
The Code
//setup for background drawing
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGContextRef context;
context = CGBitmapContextCreate(NULL, 250, backgroundHeight - 112, 8, 250 * 4, colorSpaceRef, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease(colorSpaceRef);
//Take the image I want drawn, convert to cgimage for background drawing
CGImageRef image = contentImage.CGImage;
CGContextDrawImage(context, CGRectMake(0, 0, 250, backgroundHeight - 112), image);
CGImageRelease(image);
CGImageRef outputImage = CGBitmapContextCreateImage(context);
imageRef = outputImage;
[self performSelectorOnMainThread:@selector(addImageToView) withObject:nil waitUntilDone:YES];
CGContextRelease(context);
CGImageRelease(outputImage);
The addImageToView Method simply create an image and adds to my UIImageView
UIImage * image = [UIImage imageWithCGImage:imageRef];
[photoView setImage:image];
These methods get called during the cellForRowAtIndexPath method, along with my method fadeInImage
[UIView animateWithDuration:.6 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
photoView.alpha = 1;
}completion:nil];
When I run, I get the Bad Access calls and crashing. I'm guessing it has something to do with the main thread and the background threads passing the images between one another. Any ideas? Thanks guys.
Soluzione
I think, as long as you didnt create an image with CGImageCreate
or used CGImageRetain
, you dont have to use CGImageRelease(image);
. It should release automatically once you stop using it. Check it out.
Altri suggerimenti
Don't release first image CGImageRelease(image);
And probably it is better to change:
CGImageRef outputImage = CGBitmapContextCreateImage(context);
imageRef = outputImage;
[self performSelectorOnMainThread:@selector(addImageToView) withObject:nil waitUntilDone:YES];
To:
CGImageRef outputImage = CGBitmapContextCreateImage(context);
UIImage* result = [UIImage imageWithCGImage:imageRef]
[self performSelectorOnMainThread:@selector(addImageToView:) withObject:result waitUntilDone:YES];
And then:
- (void) addImageToView:(UIImage*) image {
[photoView setImage:image];
}
Or even:
[photoView performSelectorOnMainThread:@selector(setImage:) withObject:result waitUntilDone:YES];