Resolving Low Memory Crashes with UIImagePickerController in iOS 7 on iPad Mini

UIImagePickerController Low Memory Crash at iOS 7 on iPad Mini

=====================================================================

In this article, we’ll explore a common issue that occurs when using UIImagePickerController in iOS 7 on the iPad Mini: low memory crashes. We’ll dive into the code and explain what’s happening behind the scenes to help you troubleshoot and prevent similar issues.

Introduction to UIImagePickerController


UIImagePickerController is a built-in Apple class that allows users to take photos or select images from their device’s gallery. When you create an instance of UIImagePickerController, you can configure it with various settings, such as camera source type, image capture mode, and more.

The Issue: Low Memory Crash on iOS 7 iPad Mini


The problem lies in the way Apple handles memory management for UIImagePickerController instances on older devices like the iPad Mini running iOS 7. When you allocate an instance of UIImagePickerController, it retains a strong reference to the view controller that created it, even after the view controller is deallocated.

This can lead to a situation where the UIImagePickerController instance remains in memory, consuming system resources, and eventually triggering a low memory warning or crash.

Code Review: The Problematic Code


Let’s examine the code snippet provided by the original poster:

if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
    UIImagePickerController *imagePickerController;
    if ([UIUtilityClass isCurrentVersionIsIOS7OrGreater]) {
        imagePickerController = [[UIImagePickerController alloc] init];
        [imagePickerController setDelegate:self];
        imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
        imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage,nil];
        imagePickerController.allowsEditing=NO;
        CGFloat scaleFactor=1.3f;

        switch ([UIApplication sharedApplication].statusBarOrientation) {
            case UIInterfaceOrientationLandscapeLeft:
                imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
                break;
            case UIInterfaceOrientationLandscapeRight:
                imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
                break;
            case UIInterfaceOrientationPortraitUpsideDown:
                imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
                break;
            default:
                break;
        }

    }
    else
    {
        imagePickerController = [[NonRotatingUIImagePickerController alloc] init];
        imagePickerController.delegate = self;
        imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
        imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage,nil];
        imagePickerController.allowsEditing = YES;
    }


    popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
    popoverController.delegate=self;
    [popoverController presentPopoverFromRect:CGRectMake(626,142,120,135) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    [imagePickerController release];
    newMedia = YES;
}

The problematic line is the release call on the imagePickerController instance. In ARC (Automatic Reference Counting), this line is unnecessary and can even cause issues.

The Solution: Remove the Release Call


In ARC-enabled projects, you don’t need to explicitly release objects that are managed by the compiler. The imagePickerController instance will be automatically released when it goes out of scope.

To fix the issue, simply remove the release call:

if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
    UIImagePickerController *imagePickerController;
    if ([UIUtilityClass isCurrentVersionIsIOS7OrGreater]) {
        imagePickerController = [[UIImagePickerController alloc] init];
        [imagePickerController setDelegate:self];
        imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
        imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage,nil];
        imagePickerController.allowsEditing=NO;
        CGFloat scaleFactor=1.3f;

        switch ([UIApplication sharedApplication].statusBarOrientation) {
            case UIInterfaceOrientationLandscapeLeft:
                imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
                break;
            case UIInterfaceOrientationLandscapeRight:
                imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
                break;
            case UIInterfaceOrientationPortraitUpsideDown:
                imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
                break;
            default:
                break;
        }

    }
    else
    {
        imagePickerController = [[NonRotatingUIImagePickerController alloc] init];
        imagePickerController.delegate = self;
        imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
        imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage,nil];
        imagePickerController.allowsEditing = YES;
    }


    popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
    popoverController.delegate=self;
    [popoverController presentPopoverFromRect:CGRectMake(626,142,120,135) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
    newMedia = YES;
}

By removing the release call, you ensure that the imagePickerController instance is properly released when it’s no longer needed, preventing low memory crashes and other issues.

Conclusion


In this article, we explored a common issue with UIImagePickerController on iOS 7 devices: low memory crashes. We examined the problematic code snippet provided by the original poster and discovered that the issue was caused by an unnecessary release call in ARC-enabled projects.

By removing the release call, we fixed the issue and ensured proper memory management for the imagePickerController instance. This fix is essential when working with UIImagePickerController on older devices like the iPad Mini running iOS 7.


Last modified on 2024-05-04