Управление памятью с изображением, сохраненным из UIImagePickerController

Я пишу приложение, в котором пользователь фотографирует себя, а затем просматривает серию представлений, чтобы настроить изображение с помощью навигационного контроллера. Это отлично работает, если пользователь делает снимок с помощью передней камеры (установленной по умолчанию на устройствах, которые ее поддерживают), но когда я повторяю процесс, я прохожу примерно половину пути, и он вылетает после выдачи предупреждения о памяти.

После профилирования в «Инструментах» я вижу, что объем памяти моего приложения составляет около 20-25 МБ при использовании изображения с передней камеры с более низким разрешением, но при использовании задней камеры каждое изменение вида добавляет еще 33 МБ или около того, пока не произойдет сбой примерно на 350 МБ (на 4S)

Ниже приведен код, который я использую для обработки сохранения фотографии в каталог документов, а затем чтения этого местоположения файла для установки изображения в UIImageView. «Прочитанная» часть этого кода перерабатывается через несколько контроллеров представления (viewDidLoad), чтобы установить изображение, которое я сохранил, в качестве фонового изображения в каждом представлении по мере продвижения.

Я удалил весь свой код модификации изображения, чтобы сократить его до минимума медведя, пытаясь изолировать проблему, и я не могу найти его.В настоящее время все, что делает приложение, — это делает фотографию в первом представлении, а затем использует эту фотографию в качестве фонового изображения еще примерно для 10 представлений, выделяя их по мере того, как пользователь перемещается по стеку представлений.

Теперь очевидно, что фотографии с более высоким разрешением будут использовать больше памяти, но я не понимаю, почему фотографии с низким разрешением, кажется, не используют все больше и больше памяти, в то время как фотографии с высоким разрешением постоянно используют все больше и больше, пока не рухнет.

Как я сохраняю и читаю изображение:

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];    
    jpgData = UIImageJPEGRepresentation(image, 1);

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSString *documentsPath = [paths objectAtIndex:0];
    filePath = [documentsPath stringByAppendingPathComponent:@"image.jpeg"];
    [jpgData writeToFile:filePath atomically:YES];    

    [self dismissModalViewControllerAnimated:YES];
    [disableNextButton setEnabled:YES];

    jpgData = [NSData dataWithContentsOfFile:filePath];
    UIImage *image2 = [UIImage imageWithData:jpgData];
    [imageView setImage:image2];
}

Теперь я знаю, что могу попробовать масштабировать изображение перед его сохранением, что я планирую изучить дальше, но я не понимаю, почему это не работает. как есть. Возможно, у меня было ложное впечатление, что ARC автоматически освобождает представления и их подпредставления, когда они покидают вершину стека.

Может ли кто-нибудь пролить свет на то, почему я накапливаю память своих устройств? (Надеюсь, что-то простое, что я совсем не замечаю) Мне как-то удалось выкинуть ARC в окно?

РЕДАКТИРОВАТЬ: Как я вызываю изображение в других моих представлениях

- (void)loadBackground
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSString *documentsPath = [paths objectAtIndex:0];
    NSString *filePath = [documentsPath stringByAppendingPathComponent:@"image.jpeg"];
    UIImage *image = [UIImage imageWithContentsOfFile:filePath];
    [backgroundImageView setImage:image];

}

Как устанавливается навигация между моими контроллерами представлений:

enter image description here

РЕДАКТИРОВАТЬ 2:

Как выглядят мои основные объявления:

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface PhotoPickerViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
    IBOutlet UIImageView *imageView;
    NSData *jpgData;
    NSString *filePath;
    UIImagePickerController *imagePicker;
    IBOutlet UIBarButtonItem *disableNextButton;
}


@end

Если актуально, как я вызываю средство выбора изображений:

- (void)callCameraPicker
{


    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == YES)
    {
        NSLog(@"Camera is available and ready");

        imagePicker.sourceType =  UIImagePickerControllerSourceTypeCamera;
        imagePicker.delegate = self;
        imagePicker.allowsEditing = NO;
        imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;

        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice *device in devices) 
        {
            if([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0) 
            {
                imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;


            }
        }


        imagePicker.modalTransitionStyle = UIModalTransitionStyleCoverVertical;

        [self presentModalViewController:imagePicker animated:YES];

    }


    else
    {
        NSLog(@"Camera is not available");
        UIAlertView *cameraAlert = [[UIAlertView alloc] initWithTitle:@"Error" 
                                                              message:@"Your device doesn't seem to have a camera!" 
                                                             delegate:self cancelButtonTitle:@"Dismiss" 
                                                    otherButtonTitles:nil];
        [cameraAlert show];

    }
}

РЕДАКТИРОВАТЬ 3: Я зарегистрировал viewDidUnload, и на самом деле он не вызывался, поэтому теперь я вызываю loadBackground в viewWillAppear и сделать мой backgroundImageViewnil в viewDidDisappear. Я ожидал, что это поможет, но это не имело никакого значения.

- (void)viewWillAppear:(BOOL)animated
{
    [self loadBackground];
}


- (void)viewDidDisappear:(BOOL)animated
{
    NSLog(@"ViewDidDisappear");
    backgroundImageView = nil;
}
8
задан Mick MacCallum 14 May 2012 в 14:15
поделиться