2014-12-06 5 views
1

У меня есть приложение, которое получает предупреждение о памяти при использовании камеры на iPhone 4s. Я масштабирую изображение, прежде чем использовать его.Понимание NSAutoreleasePool

+ (UIImage*)simpleImageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize 
{ 

// Create a graphics image context 
UIGraphicsBeginImageContext(newSize); 

// Tell the old image to draw in this new context, with the desired 
// new size 
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 

// Get the new image from the context 
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 

// End the context 
UIGraphicsEndImageContext(); 


// Return the new image. 
return newImage; 
} 

Я читал, что вы должны использовать NSAutoreleasePool здесь http://wiresareobsolete.com/2010/08/uiimagepickercontroller/

Так что я изменил код так:

+ (UIImage*)simpleImageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize 
{ 
//http://wiresareobsolete.com/2010/08/uiimagepickercontroller/ 

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

// Create a graphics image context 
UIGraphicsBeginImageContext(newSize); 

// Tell the old image to draw in this new context, with the desired 
// new size 
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 

// Get the new image from the context 
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 

// End the context 
UIGraphicsEndImageContext(); 

[newImage retain]; 

[pool release]; 

// Return the new image. 
return newImage; 
} 

предупреждение памяти пошел прочь. Я не называл это в отдельном потоке. Что это такое NSAutoreleasePool делать? Я просто этого не понимаю.

Могу ли я удерживать объект в местном NSAutoreleasePool?

Могу ли я использовать сохраненный объект после NSAutoreleasePool был выпущен?

Важный вопрос: Как это специфическое использование в NSAutoreleasePool помощью памяти след моего приложения, так что он не получает предупреждения памяти?

+0

Современная форма '@ autoreleasepool' ... в общем, то, что происходит, когда пул сливается, заключается в том, что объекты с автореализацией с нулевым количеством удержания освобождаются, поэтому вы вынуждаете dealloc при сливе пула. Явное 'сохранение' должно генерировать предупреждение/ошибку ... – stevesliva

+0

Явное сохранение newImage не вызывает предупреждения/ошибки. –

+0

Вы не используете ARC? – stevesliva

ответ

0

NSAutoreleasePool, создаваемый себя просто вызывает метод освобождения для объектов autorelease в его районе, где от NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; до [pool release];,

Здесь

UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 

newImage является объект autorelease, [newImage release] будет называться после [pool release];

Если нет [newImage retain];newImage будет deallo c после [pool release];

  1. Вы можете сохранить объект в локальном NSAutoreleasePool.
  2. Вы можете использовать сохраненный объект после освобождения NSAutoreleasePool.
  3. Используйте NSAutoreleasePool для освобождения временной памяти.
+0

Создает ли UIGraphicsGetImageFromCurrentImageContext несколько крупных объектов, отмеченных авторекламой? В противном случае я не понимаю, как это фактически уменьшило использование памяти. Это потому, что NSAutoreleasePool выпущен так, что, когда я позже вызываю release на newImage, который был возвращен, он мгновенно освобождает память вместо того, чтобы просто уменьшать счетчик, чтобы освободить память позже? –

+0

Он должен иметь объекты автоопределения в системных образных методах, я не читал источник 'UIGraphicsGetImageFromCurrentImageContext', я не могу его подтвердить. Да, то, что вы сделали с newImage, не поможет освободить память, но поможет сохранить newImage, который можно использовать после выпуска autoreleasePool. – simalone

+0

Любая идея по последней части моих вопросов? Почему это приводит к тому, что iOS перестает выдавать предупреждение о памяти?Предусмотрены ли предупреждения памяти, когда AutoreleasePool (ARP) достигает некоторой отметки о высокой воде? если в ARP есть объекты, которые используют X объем памяти, а X больше некоторого значения, тогда iOS отправляет предупреждение о памяти? Я упрощу пример. Предположим, что max составляет 100 единиц памяти. Если у меня есть ARP 1, и у него есть объекты, которые используют 99 единиц памяти, и я добавляю другой объект, тогда iOS отправляет предупреждение? Если бы у меня было два пула ARP 1 и ARP 2 с объектами, использующими 99 единиц памяти, тогда никаких предупреждений? –

4

Прежде всего, вы должны использовать @autoreleasepool блоков вместо NSAutoreleasePool объектов; последнее довольно устарело. Первое лучше, потому что оно автоматически истощает пул, когда вы покидаете область действия блока, не требуя явно сделать это самостоятельно.

Пул авторефератов просто запоминает вещи, которые были «автореализованы» в то время как в его объеме, и освобождает их, когда бассейн слит. «Autoreleasing» объект похож на его освобождение, но отложен; с точки зрения управления памятью, она требует сильной ссылки, которую вы имеете, и «передает» ее в пул, так что теперь у пула есть ссылка на объект, а вы этого не делаете. В pre-ARC, если метод (имя которого не начиналось с new или copy), необходимо вернуть объект, который был создан во время функции, его в значительной степени пришлось автореализовать. Поместив его в пул, он гарантирует, что объект будет живой, чтобы его принимала вызывающая функция.В вашем коде UIGraphicsGetImageFromCurrentImageContext() скорее всего вернет автореализованный объект.

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

Например, один запуск вашей функции автоматически разрешает один объект (т. Е. Объект возвращается UIGraphicsGetImageFromCurrentImageContext()). Затем, если вы запустите свою функцию 100 000 раз в цикле, 100 000 объектов остаются в памяти, потому что они попадают в тот же пул, который еще не успел слить. Однако, если вы добавите еще один уровень пула в каждую итерацию цикла, он будет стекать в конце каждой итерации, предотвращая создание объектов.

Что касается вашего второго фрагмента кода, то размещение автореферата в вашем simpleImageWithImage: методе позволяет получить автореферат от UIGraphicsGetImageFromCurrentImageContext(). Однако у вас есть другая проблема, потому что , чтобы вернуть объект изображения из самого метода simpleImageWithImage:, вам необходимо авторейтировать его!

Ваш метод, как написано, нарушает правила управления памятью. Ваш метод возвращает сохраненный объект, который вызывающий должен запомнить для выпуска. Однако вызывающий абонент не знает этого, основываясь на имени. В соответствии с соглашениями об именах единственными методами, которые могут вернуть сохраненный экземпляр, являются те, чьи имена начинаются с alloc, retain, new, copy и mutableCopy. Ваш метод не запускается ни с одним из них, поэтому он должен возвращать неудерживаемый экземпляр. Поскольку вы владеете объектом (сохраняя его), вы должны выполнить балансировку или авторекламу. Вы не можете освободить его, потому что это приведет к тому, что объект будет потенциально освобожден, так как нет других сильных ссылок на него, поэтому вы можете его автообновить.

Но если вы собираетесь автореализовать его снова, вы ничего не достигли, добавив здесь автореферат, если только внутри drawInRect: или внутри UIGraphicsGetImageFromCurrentImageContext() они не автореклассируют много материала.

 Смежные вопросы

  • Нет связанных вопросов^_^