Причина большого выделения памяти (утечка памяти?) При чтении UIImage с камеры - PullRequest
1 голос
/ 22 февраля 2012

Я пытаюсь изменить FGallery (https://github.com/gdavis/FGallery-iPhone). Мне это нужно, чтобы прочитать изображения с камеры, но я получаю утечку памяти.

Старый код (путь к файлу):

@autoreleasepool {

NSString *path = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle]   bundlePath],_thumbUrl];
_thumbnail = [UIImage imageWithContentsOfFile:path];
_hasThumbLoaded = YES;
_isThumbLoading = NO;
[self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil   waitUntilDone:YES];
}

Мой код (путь к URL-адресу библиотеки утверждений):

@autoreleasepool {

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
   ALAssetRepresentation *rep = [myasset defaultRepresentation];
   CGImageRef iref = [rep fullResolutionImage];
   if (iref) {
       _thumbnail = [UIImage imageWithCGImage:iref];
       _hasThumbLoaded = YES;
       _isThumbLoading = NO;
       [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil   waitUntilDone:YES];
   }
};        

ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror) {
   NSLog(@"booya, cant get image - %@",[myerror localizedDescription]);
};     

NSURL *asseturl = [NSURL URLWithString:_thumbUrl];
[assetslibrary assetForURL:asseturl 
resultBlock:resultblock
failureBlock:failureblock];
}
}

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

Есть идеи, почему?

P.S. Я использую ARC, и сделал автоматический переход для FGallery. Он отлично работает для изображений локальных приложений, но, как уже было сказано, я не могу заставить его работать с изображениями с камеры.

редактировать 1: сбой программы

Ответы [ 4 ]

6 голосов
/ 23 февраля 2012

я думаю, что понял.«Результирующий блок ALAssetsLibraryAssetForURLResultBlock» выполняется в другом потоке.и поэтому @autoreleasepool к нему не относится.(у каждого потока есть свой пул автоматического выпуска).следовательно, объем памяти намного выше из-за большого количества «автоматически выпущенных» выделений (изображений).добавление "@autoreleasepool" внутри блока остановило сбои и большое выделение памяти. Короче

:

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
   @autoreleasepool {
      ALAssetRepresentation *rep = [myasset defaultRepresentation];
      CGImageRef iref = [rep fullResolutionImage];
      if (iref) {
          _thumbnail = [UIImage imageWithCGImage:iref];
          _hasThumbLoaded = YES;
          _isThumbLoading = NO;
          [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil   waitUntilDone:YES];
       }
   }
}; 

спасибо всем, кто ответил.

4 голосов
/ 23 февраля 2012

Если нет необходимости в изображении с полным разрешением, вам, вероятно, будет лучше использовать:

CGImageRef iref = [rep fullScreenImage];

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

Это сэкономит много памяти.

0 голосов
/ 16 марта 2015

Как пользователь Picciano , упомянутый в его посте, если возможно, вы должны использовать вызов [rep fullScreenImage]; вместо запроса полноразмерного изображения.Это сэкономит много места.Тем не менее, в моем случае это было невозможно, потому что мне нужно отправить изображение с более высоким разрешением на внешний сервер позже.Что вы можете сделать, так это использовать шкалу, чтобы максимально изменить ее размер:

CGFloat originalRatio = assetRepresentation.dimensions.width / assetRepresentation.dimensions.height;
CGFloat wantedRatio = maxSize.width / maxSize.height;
CGFloat scale = 1;

if (originalRatio < wantedRatio)
{
    scale = maxSize.height / assetRepresentation.dimensions.height;
}
else
{
    scale = maxSize.width / assetRepresentation.dimensions.width;
}

CGImageRef ref = [assetRepresentation fullResolutionImage];
UIImage *image = [UIImage imageWithCGImage:ref
                                     scale:scale orientation:orientation];

Что это в основном определяет, сколько мы можем масштабировать изображение (определяется как maxSize).Это спасло нас достаточно, чтобы предотвратить утечки памяти.

0 голосов
/ 22 февраля 2012

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

Утечка памяти происходит, когда у вас есть объекты, на которые нет ссылок, которые не были освобождены.Вы можете использовать инструмент анализа компилятора, чтобы увидеть возможные утечки.Это не найдет их всех, поэтому вы можете использовать инструменты, чтобы увидеть, где могут происходить другие.Но пока вы не проверили эти инструменты, вы не можете точно сказать, что у вас есть утечка, которая не очевидна, глядя на код.

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

ОБНОВЛЕНИЕ

Показать код для класса ALAssetRepresentation.Возможно, вы не выпускаете что-то там.

...