Вопрос

Подобно известной проблеме утечки памяти, связанной с созданием и уничтожением экземпляра UIImagePickerController, я обнаруживаю аналогичные проблемы с экземплярами класса UIViewController.Рекомендуемый способ использования UIImagePickerController — создать экземпляр один раз и сохранить его на протяжении всего срока службы приложения, даже если при этом будет использована память, которая может вам понадобиться в другом месте.

Ситуация, с которой я имею дело, включает в себя два экземпляра класса UIViewController.При запуске создается первый экземпляр, и его представление добавляется в другой «основной» класс UIViewController, который является частью MainWindow.xib.В этом первом экземпляре находится кнопка «информация», при нажатии на которую переключается на новый экземпляр класса UIViewController (если он еще не был создан).«Основной» UIViewController управляет этим переключением с помощью обычной анимации переворота.Базовую настройку можно увидеть в разделе «Начало разработки iPhone:Книга «Изучаем iPhone SDK» Дэйва Марка.

Проблема, которая возникает, заключается в том, что после первого нажатия кнопки «информация» память выделяется для нового второго экземпляра UIViewController и не освобождается до тех пор, пока приложение не завершится.Из-за количества элементов в этом информационном представлении после создания экземпляра оно использует около 1 МБ памяти, и его представление добавляется в суперпредставление.Любые попытки последовательно уничтожить и воссоздать этот экземпляр приводят к утечке памяти, аналогичной той, которая возникает, если вы попытаетесь сделать то же самое с экземплярами класса UIImagePickerController.Я подозреваю, что основная причина у этих двух классов одна и та же.

Суть моей проблемы заключается в необходимости освободить как можно больше памяти, прежде чем я позволю пользователю сделать снимок с помощью камеры.Однако, как только пользователь сделал снимок и увидел полученное изображение в первый раз, ему разрешено нажать кнопку «информация», которая существует в первом экземпляре UIViewController.После нажатия «основной» UIViewController удаляет существующее представление UIViewController и заменяет его представлением информационного экрана.На информационном экране есть кнопка «Назад», позволяющая переключить вид обратно.Однако, как только пользователь покидает информационный экран и решает сделать еще один снимок с помощью камеры, память, выделенная для информационного экрана, все еще остается в памяти.

Класс UIImagePickerController временно использует почти 15–18 МБ, пока он обрабатывает 2-мегапиксельное изображение перед освобождением внутренних ссылок и вызывается делегат imagePickerController:didFinishPickingImage.Я сталкиваюсь с оповещениями о нехватке памяти после того, как второй экземпляр UIViewController был создан с помощью кнопки информации, а затем пользователь решил сделать еще один снимок.

Технически память не протекает независимо от того, делаете ли вы снимки снова и снова, нажимая на кнопку информации или без нее, в моем случае, но из-за других проблем, связанных с фоновыми процессами на iPhone (Safari и т. д.), которые находятся вне вашего контроля, вы ДОЛЖНЫ освободить используйте как можно больше памяти при работе с такими вещами, как камера.

Есть какие-нибудь советы о том, как аккуратно создавать и уничтожать экземпляры класса UIViewController, чтобы не было утечки памяти?

Это было полезно?

Решение

Вы загружаете второй контроллер представления из NIB?Если это так, вам следует проверить, правильно ли вы освобождаете связанную память.

Вот как выглядит типичный контроллер представления на основе NIB в моих проектах.

SomeViewController.h

@interface SomeViewController : UIViewController {
    UILabel *someLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *someLabel;

@end

SomeViewController.m

@implementation SomeViewController

@synthesize someLabel;

- (void)dealloc {
    // Release our retained IBOutlets
    self.someLabel = nil;
    [super dealloc];
}

@end

Другие советы

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

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

Еще одна статья здесь показывает использование одноэлементного класса (хотя и отличается от вашего варианта использования, но поясняет, как использовать синглтоны)

Я бы предложил также создать одноэлементный объект для UIImagePickerController.

Есть ли у вас циклы в цепочке владения?Что-то вроде:

@interface FirstViewController: UIViewController {
  SecondViewController *secondViewController;
}
@end

@interface SecondViewController: UIViewController {
  FirstViewController *firstViewController;
}
@end

Если вы явно не разорвете этот цикл, отбрасывая эти контроллеры представления, они протекут.

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

Возможно, вы могли бы сохранить изображение перед переходом в режим просмотра информации.После сохранения отпустите изображение и перейдите в режим просмотра информации.Если пользователь вернется, загрузите изображение из папки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top