Saving UIImagePickerController images to Core Data without crashing

Posted by Gordon Fontenot on Stack Overflow See other posts from Stack Overflow or by Gordon Fontenot
Published on 2010-06-15T00:09:45Z Indexed on 2010/06/15 0:12 UTC
Read the original article Hit count: 525

I have been trying to minimize my memory footprint with UIImagePickerController, but I'm starting to think that the memory problems I am having are resulting from poor memory management, instead of a particular way to handle the UIImagePickerController object.

My workflow is this: The "Edit Image" button is clicked, which presents a UIActionSheet. This action sheet allows you to delete, take a picture, choose from the library, or cancel. If you select Choose from the library or Take Picture, I alloc an instance of UIImagePickerController and present it, followed by a release of UIImagePickerController:

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (actionSheet.tag != 999) {
        UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
        imagePicker.delegate = self;

        BOOL pickImage = nil;

        if (actionSheet.tag == iPhoneWithDelete) {
            switch (buttonIndex) {
                case 0:
                    object.objectImage = nil;
                    pickImage = NO;
                    break;
                case 1:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
                    pickImage = YES;
                    break;
                case 2:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }
        } else if (actionSheet.tag == iPhoneNoDelete) {
            switch (buttonIndex) {
                case 0:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
                    pickImage = YES;
                    break;
                case 1:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }       
        } else if (actionSheet.tag == iPodWithDelete) {
            switch (buttonIndex) {
                case 0:
                    object.objectImage = nil;
                    pickImage = NO;
                    break;
                case 1:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }
        } else if (actionSheet.tag == iPodNoDelete) {
            switch (buttonIndex) {
                case 0:
                    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                    pickImage = YES;
                    break;
                default:
                    pickImage = NO;
                    break;
            }
        }

        if (pickImage) {
            imagePicker.allowsEditing = YES;
            [self presentModalViewController:imagePicker animated:YES];
        } else {
            [self setupImageButton];
            [self setupChooseImageButton];
        }
        [imagePicker release];
    }
}

Once I get a selection back from the UIImagePickerController, I save 2 images, a resized version of the edited image to use for a thumbnail, and a 800x600 version of the original unedited image into a relationship attribute (Transformational, using the same UIImage to PNG transformations found in the Recipes demo code) for display use: (the resize methods are based on the one demoed in this SO post.)

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{

    [self dismissModalViewControllerAnimated:YES];

    NSManagedObject *oldImage = object.imageFull;
    if (oldImage != nil)
    {
        [object.managedObjectContext deleteObject:oldImage];
    }

    NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:object.managedObjectContext];
    object.imageFull = image;

    UIImage *rawImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];

    CGSize size = CGSizeMake(800, 600);

    UIImage *fullImage = [UIImageManipulator scaleImage:rawImage toSize:size];

    [image setValue:fullImage forKey:@"imageFull"];

    UIImage *processedImage = [UIImageManipulator scaleImage:[info objectForKey:@"UIImagePickerControllerEditedImage"] toSize:CGSizeMake(75, 75)];
    object.objectImage = processedImage;
    [self setupImageButton];
    [self setupChooseImageButton];

    rawImage = nil;
    fullImage = nil;
    processedImage = nil;
}

When I go through viewDidUnload I am setting self.object = nil, and [object release] during dealloc, but I'm still getting memory warnings after about 10 image changes, with a crash at around 20. It leads me to believe that I am not getting that full image out of memory the correct way. What am I missing here?

And on a second note, does the Camera source use significantly more memory than the Photo Albums source? I tend to get more crashes when using the camera.

© Stack Overflow or respective owner

Related posts about memory-management

Related posts about core-data