p0lAris
p0lAris

Reputation: 4820

Resizing an image in iOS — undiagnosable leak

I have the following code picked from answers on StackOverflow:

+ (UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)newSize;
{
    // UIGraphicsBeginImageContext(newSize);
    // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
    // Pass 1.0 to force exact pixel size.

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 1.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

I am using this as a category for the UIImage type. I am profiling it in the following method:

+ (void)testResize:(UIImage *)image
{
    clock_t start = clock();
    int times = 50;
    for (int i = 0; i < 50; i++) {
        // resize photo
        UIImage *resizedImage = [UIImage resizeImageToOptimalSize:image];
        resizedImage = nil;
    }
    double diff = (double)clock()-start;
    printf("testResize = %f\n", diff * 1000/times/CLOCKS_PER_SEC);
}

It doesn't matter if I modify the above code and just dump the resizeImageToOptimalSize call 50 times, I see the profiler going nuts. Here is the resizeImageToOptimalSize code just in case you wonder I made a blunder here:

+ (UIImage *)resizeImageToOptimalSize:(UIImage *)image
{
    CGSize newSize = CGSizeMake(..., ...);
    return [self resizeImage:image toSize:newSize];
}

The memory usage increases and goes up and then drops to ~ 1.5MB when the method finishes. Here is the instruments screenshot:

Instruments screenshot for <code>resizePhoto</code> running on iPhone 4S

There are no leaks per se from the Instruments tool but I don't believe it. It's either the for loop not letting go of resizedImage or if something's going on with the context (not sure).

Upvotes: 0

Views: 244

Answers (1)

Timur Kuchkarov
Timur Kuchkarov

Reputation: 1155

You need to add @autoreleasepool inside the for loop.

    for (int i = 0; i < 50; i++) {
    @autoreleasepool {
            // resize photo
            UIImage *resizedImage = [UIImage resizeImageToOptimalSize:image];
        }
    }

Also you don't need to set resizedImage to nil. Image is autoreleased(at least without optimizations).

Upvotes: 1

Related Questions