Reputation: 41665
I have following code as UIImage+Scale.h category.
-(UIImage*)scaleToSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[self drawInRect:CGRectMake(0, 0, size.width, size.height)];
// is this scaledImage auto-released?
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
I use image obtained as above and use it as following.
UIImage* image = [[UIImage alloc] initWithData: myData];
image = [image scaleToSize: size]; <- wouldn't this code create a leak since
image(before scaling) is lost somewhere?
i guess above codes work fine if image was first created with auto-release.
But if image was created using 'alloc', it would create a leak in my short knowledge.
How should I change scaleToSize: to guard against it?
Thank you
I'd like to use alloc(or retain)/release on UIImage so that I can keep the # of UIImage in memory at a point small.
(i'm loading many UIImages in a loop and device can't take it)
Upvotes: 0
Views: 432
Reputation:
Notice that your code could be rewritten as:
UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
image = scaledImage;
so let’s see what happens:
image
is obtained via alloc
, hence you own that objectscaledImage
is obtained via a method that returns an autoreleased object since UIGraphicsGetImageFromCurrentImageContext()
returns an autoreleased objectimage
but you don’t own scaledImage
. You are responsible for releasing the original image
, otherwise you have a leak.In your code, you use a single variable to refer to both objects: the original image and the scaled image. This doesn’t change the fact that you own the first image, hence you need to release it to avoid leaks. Since you lose the original image reference by using the same variable, one common idiom is to send -autorelease
to the original object:
UIImage *image = [[[UIImage alloc] initWithData:myData] autorelease];
image = [image scaleToSize:size];
Or, if you’d rather release the original image instead of autoreleasing it,
UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
[image release];
// use scaledImage from this point on, or assign image = scaledImage
IMO, it doesn’t make sense to change scaleToSize:
. It is an instance method that creates an (autoreleased) image based on a given UIImage
instance. It’s similar to -[NSString stringByAppendingString:]
, which creates a (an autoreleased) string based on a given NSString
instance. It doesn’t and shouldn’t care about the ownership of the original string, and the same applies to your scaleToSize:
method. How would the method know whether the caller wants to keep the original image?
I’d also rename scaleToSize:
to imageByScalingToSize
to make it similar to Cocoa’s naming convention — you’re getting an image by applying an operation to an existing image.
Upvotes: 2
Reputation: 18741
Yeah, it is sure that you have a leak. The object stored previously in the image is not referenced anymore but not deallocated yet
Upvotes: 1