Хобрук: Ваш путь к мастерству в программировании

Objective-c UIImagePNGRepresentation, вызывающий утечку памяти

Я пытаюсь загрузить и сохранить некоторые изображения (преобразованные из строки base64 в UIImage) на устройство и продолжаю получать предупреждение о памяти.

ontracFullScreenImageViewController *etrackDiagrams = ((ontracFullScreenImageViewController*)[viewControllerDictionary objectForKey:@"E-track Diagrams"]);
    NSMutableSet *etrackSet = [[NSMutableSet alloc] init];

    for (UIImage *image in etrackDiagrams.imageArray) {


        NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
        //convert the image to NSData and store it in the documents directory
        NSData *pngData = UIImagePNGRepresentation(image);
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
        NSString * timeInMS = [NSString stringWithFormat:@"%lld", [@(floor([[NSDate date] timeIntervalSince1970] * 1000)) longLongValue]];
        NSString *filePath = [documentsPath stringByAppendingPathComponent:[ NSString stringWithFormat:@"%@_%@_etrack_diagram_%i_%i_image.png", delegate.userName, timeInMS, self.dataObject.dataPack.pack_id, [etrackDiagrams.imageViewArray indexOfObject:image]]]; //Add the file name
        [pngData writeToFile:filePath atomically:YES];
        NSLog(@"filepath %@", filePath);
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        if ([currSysVer isEqualToString:@"5.0.1"]) {
            [[NSURL URLWithString:filePath] setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error];
        }
        //Add the file Path to ImageLinks
        [etrackDiagrams.imageLinks addObject:filePath];
        //save the image location in Core Data
        EtrackDiagram *etrackDiagram = [NSEntityDescription
                                        insertNewObjectForEntityForName:@"EtrackDiagram"
                                        inManagedObjectContext:context];
        etrackDiagram.locationString = filePath;
        etrackDiagram.dataObject = dataObject;
        [etrackSet addObject:etrackDiagram];
        [dataObject addEtrackDiagramsObject:etrackDiagram];
        [localPool drain];

    }
    [dataObject addEtrackDiagrams: etrackSet];

Предупреждение о памяти появляется в NSData *pngData = UIImagePNGRepresentation(image);, так как изображения довольно большие.

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

Я пытался обернуть код @autoreleasepool, но это не имело значения.


  • Попробуйте обернуть свой код с помощью @autoreleasepool, как предлагается здесь: stackoverflow.com/a/9779032/1689376 11.10.2016
  • @alex Я уже пробовал это, но безуспешно. Соответственно обновил мой вопрос. 11.10.2016

Ответы:


1

Настоящая проблема заключается в этой строке:

for (UIImage *image in etrackDiagrams.imageArray) {

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

11.10.2016
  • У вас есть хороший момент здесь. Что я сделал сейчас, так это попытался сохранить изображение по мере его извлечения из URL-адреса (отдельно). Но радости все равно нет :/ 11.10.2016
  • если изображение сохраняется на диск по мере его извлечения, зачем вам нужно снова преобразовывать его в данные Png? Это данные. Он сохранен. У него есть путь. Сделанный. 11.10.2016
  • Это строка base64, которую я конвертирую в png, чтобы ее можно было использовать в галерее. 11.10.2016
  • Нет, не слежу. У вас не отображается ни одна галерея сейчас. Загруженные данные являются данными изображения. Сказать, что base64 ничего не добавляет к истории, не так ли? Это просто означает, что вы скачали его, и мы это уже знаем. 11.10.2016
  • Позвольте мне сказать это по-другому. Строка for (UIImage *image in etrackDiagrams.imageArray) доказывает, что вы можете получить объекты UIImage из загруженных данных. Но затем вы можете получить объекты UIImage из загруженных данных после того, как эти данные будут сохранены на диск. Вам не нужно выполнять какое-то промежуточное преобразование в PNG, чтобы пересохранить эти данные. Он уже готов к рок-н-роллу. 11.10.2016
  • Кроме того, сохранив загруженное изображение на диск, если вам действительно действительно нужно преобразовать его в формат PNG, вы можете сделать это напрямую с диска на диск, без какой-либо нагрузки на память, с помощью инфраструктуры ImageIO. 12.10.2016

  • 2

    вот код, чтобы доказать, что теория Мэтта была неверной.

    for(NSInteger i =0; i < etrackDiagrams.imageArray.count; i ++) {
       UIImage *image = etrackDiagrams.imageArray[i];
       // here is your code to save image in device.
    }
    

    если "for(uiimage *image in imagearray)" содержит массив изображений в памяти, то приведенный выше код решит проблему, но на самом деле это в основном без какой-либо помощи.

    Предупреждение о памяти появляется в NSData *pngData = UIImagePNGRepresentation(image); так как изображения довольно большие. Я думаю, что это сообщение очень важно!!!

    вот у кого-то была такая же проблема. нажмите здесь

    11.10.2016

    3

    Может быть, вы передумаете:

    1. когда вы загружаете строку base64, преобразуйте ее в nsdata, а затем добавляйте в свой массив;
    2. когда вы хотите сохранить данные изображения, выберите nsdata в своем массиве.

    если вы не хотите показывать изображение в некоторых представлениях, вам не нужно обращать внимание на предупреждение о памяти.

    11.10.2016
    Новые материалы

    Решения DBA Metrix
    DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

    Начало работы с Блум
    Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

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

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...