проблема памяти при сохранении изображений с помощью UIImagePNGRepresentation - PullRequest
1 голос
/ 07 марта 2011

Мое приложение использует множество масштабированных изображений в анимации.Чтобы избежать пропуска кадров, я масштабирую свои изображения и сохраняю их перед запуском анимации.Вот мой код для сохранения изображений:

+ (void)saveImage:(UIImage *)image withName:(NSString *)name {
    NSData *data = UIImagePNGRepresentation(image);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *directory = [paths objectAtIndex:0];
    NSString *fullPath = [directory stringByAppendingPathComponent:name];
    [fileManager createFileAtPath:fullPath contents:data attributes:nil];

}

К сожалению, когда я повторно вызываю эту функцию, у меня возникают проблемы с памятью.Я думаю, что я пытаюсь сохранить изображения около 10 МБ.Я думаю, что, возможно, проблема с автоматически выпущенными переменными - возможно, я должен распределить данные и выпустить в конце.Но я не могу найти версию alloc UIImagePNGRepresentation.Кто-нибудь может помочь?

Ответы [ 2 ]

4 голосов
/ 07 марта 2011

UIImagePNGRepresentation возвращает автоматически выпущенный объект NSData.Другими словами, выделенные данные будут освобождены только после того, как вы доберетесь до вызова освобождения (или утечки) ближайшего вмещающего блока NSAutoreleasePool.

Если вы вызываете вышеуказанный код из цикла, возможно, ваш код никогда не получит возможность автоматически высвободить всю эту память.В такой ситуации вы можете заключить ваши вызовы в свой собственный NSAutoreleasePool:

for (int i = 0; i < 10; i++) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [self saveImage:someImage withName:@"someName.png"]; 

    [pool drain];
}

Примечание: я считаю, что работать с PNG таким образом довольно медленно по сравнению с использованием JPG (UIImageJPGRepresentation).Просто к вашему сведению.

1 голос
/ 07 марта 2011

Как выглядит внешний цикл? Если это что-то вроде:

for(n = 0; n < 1000; n++)
{
    ... something ...
    [class saveImage:image withName:name];
}

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

+ (void)saveImage:(UIImage *)image withName:(NSString *)name {
    // create a local autorelease pool; this one will retain objects only
    // until we drain it
    NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];

    NSData *data = UIImagePNGRepresentation(image);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *directory = [paths objectAtIndex:0];
    NSString *fullPath = [directory stringByAppendingPathComponent:name];
    [fileManager createFileAtPath:fullPath contents:data attributes:nil];

    // drain the pool, which acts like release in reference counted environments
    // but also has an effect in garbage collected environments
    [localPool drain];
}

Таким образом, для каждого сохранения изображения вы создаете свой собственный пул автоматического выпуска. Последний инициализированный пул авто-релизов автоматически настраивается на перехват всех автоматически выпущенных объектов. В среде сборки мусора, такой как iOS, вызов «утечки» приводит к ее освобождению и немедленному освобождению всех объектов, которые он содержит.

...