#objective-c #ios #nsfilemanager
#objective-c #iOS #nsfilemanager
Вопрос:
У меня утечка памяти, которая приводит к сбою моего приложения при копировании / создании изображений в NSFileManager.
Когда я профилирую свое приложение с помощью «Allocations», все выглядит нормально. Выделяемая память увеличивается примерно с 1,5 МБ до 6 МБ при каждом повторном обращении, а затем снова уменьшается до 1,5 МБ.
Но «Реальная память» и «Виртуальная память» увеличиваются примерно до 150 МБ, а затем приложение выходит из строя.
Я получаю предупреждения о памяти уровня 1 и 2 ранее.
вот функция, которую мы используем:
-(void) processCacheItems:(NSMutableArray*) originalFiles
{
if ( [originalFiles count] == 0 )
{
[originalFiles release];
return;
}
else
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *curFileName = [originalFiles lastObject];
NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:curFileName];
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
CGSize destinationSize = CGSizeMake(150,150);
CGSize previewDestinationSize = CGSizeMake(1440.0, 1440.0);
UIImage *originalImage = [UIImage imageWithContentsOfFile:filePath]; // AUTORELEASED
// create thumb and copy to presentationfiles directory
UIImage *thumb = [originalImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
bounds:destinationSize
interpolationQuality:kCGInterpolationHigh]; // AUTORELEASED
// the resizedImageWithContentMode: does not semm to make the problem, because when i skip this and just use the original file the same problem occours
NSString *thumbPath = [thumbsDirectoryPath stringByAppendingPathComponent:curFileName];
[fileManager createFileAtPath:thumbPath contents:UIImageJPEGRepresentation(thumb, 0.9) attributes:NULL];
// create thumb and copy to presentationfiles directory
UIImage *previewImage = [originalImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
bounds:previewDestinationSize
interpolationQuality:kCGInterpolationHigh]; // AUTORELEASED
NSString *previewImagePath = [previewsDirectoryPath stringByAppendingPathComponent:curFileName];
[fileManager createFileAtPath:previewImagePath contents:UIImageJPEGRepresentation(previewImage, 0.9) attributes:NULL];
// copy copy original to presentationfiles directory
NSString *originalPath = [originalFilesDirectoryPath stringByAppendingPathComponent:curFileName];
[fileManager copyItemAtPath:filePath toPath:originalPath error:NULL];
[originalFiles removeLastObject];
[pool drain];
[self processCacheItems:originalFiles]; // recursion
}
}
Комментарии:
1. Перейдите в настройки сборки и включите «Запустить статический анализатор».
2. используйте инструмент instrument, чтобы найти место утечки памяти..
3. @iAmitWagh я не вижу этого в инструментах, используя утечки памяти.. В разделе «Распределения» это тоже выглядит неплохо..
4. @WTP. Я включил «Запустить статический анализатор», что я могу видеть теперь? и где?
5. Я не вижу какой-либо очевидной утечки в вашем коде, но использование рекурсии и освобождение массива, когда он пуст, не лучший способ организовать это. Почему бы вам просто не выполнить итерацию по массиву и не освободить его впоследствии? Имя метода
processCacheItems:
не указывает на то, что он будет освобождать аргумент, который вы ему даете.
Ответ №1:
Спасибо за подсказку.
Мне нравится, что проблема была не в утечке, а в слишком большом распределении памяти при уменьшении размера больших изображений в «resizedImageWithContentMode:» Это привело к сбою приложения.
Я изменил масштабирование изображения, чтобы использовать платформу ввода-вывода изображений. Теперь все работает нормально.
Ответ №2:
ОБНОВЛЕНИЕ: этот ответ устарел. Если вы используете ARC, игнорируйте это.
Как вы распределяете NSFileManager?
Я столкнулся с тем, что выделение его с помощью defaultManager
метода, который устарел, приводит к утечкам памяти (или так говорят инструменты, инструменты иногда сообщают об утечках памяти там, где их нет).
Как правило, вы должны выделить его с помощью [[NSFileManager alloc] init]
и освободить, когда оно вам больше не понадобится.