UINavigationController: освобождает память ViewController при извлечении

#iphone #objective-c #ios #ipad #uinavigationcontroller

#iPhone #objective-c #iOS #iPad #uinavigationcontroller

Вопрос:

Я видел несколько сообщений на эту тему здесь, на SO, но никаких окончательных ответов. Вот моя проблема.

У меня есть UINavigationController файл, который я использую как галерею. На первом контроллере я загружаю кучу удаленных изображений. Это увеличивает объем моей памяти, но не так сильно. При нажатии на изображение оно нажимает на другое viewController , на котором только что щелкнули изображения для галереи. Это может привести к загрузке еще 1 МБ или более данных из этих изображений.

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

Есть ли какой-либо способ освободить эту память при viewController извлечении? Возможно, в моем viewDidDisappear: методе? Если да, то что бы я выпустил? И как я могу создать его снова? Я пробовал это до такой степени, как освобождение моего представления, но я получаю сбои.

Есть понимание этой проблемы?

 PhotosGalleryiPad *gallery = [[PhotosGalleryiPad alloc] init];
gallery.items = self.items;
gallery.asset = self.currentAsset;
[self.navigationController pushViewController:gallery animated:YES];
;
  

Комментарии:

1. Honestly…it похоже, память действительно должна выгружаться при «освобождении» загруженного вами представления, когда вы извлекаете его из стека. Вы уверены, что правильно освобождаете все данные фотографии в dealloc? Если вы каким-то образом не позволяете пользователю бесконечно перемещаться по нескольким представлениям, даже не нажимая кнопку «Назад»… представления в навигаторе просмотра обычно должны освобождаться при нажатии кнопки «Назад» в заголовке. Если это так, то вы можете захотеть взглянуть на другую парадигму навигации.

2. Нет, вызывается dealloc, и мои свойства освобождаются. Они просто щелкают, нажимают на контроллер, затем нажимают обычную кнопку «назад», чтобы вернуться к корню.

Ответ №1:

Обычно вы освобождаете любую память в dealloc методе контроллера представления, который извлекается из стека.

Однако, если вы говорите об изображениях, и вы их загрузили [UIImage imageNamed:] , тогда UIKit может их кэшировать. Попробуйте подделать предупреждение о памяти в симуляторе (из меню оборудования) и посмотрите, выгружает ли это эти кэшированные изображения.

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

Ответ №2:

Где именно вы сохраняете эти изображения галереи?

Позвольте мне предположить, что gallery.items это изменяемая коллекция (возможно, массив), содержащая изображения. По мере того, как пользователь посещает новые галереи, в этот массив добавляется больше изображений. От контроллера представления к контроллеру представления вы передаете указатель на этот массив:

 gallery.items = self.items;
  

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

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

 gallery.items = [self.items mutableCopyWithZone:nil];
  

Затем, когда извлекается контроллер представления, его items массив освобождается. Объекты, добавленные извлеченным контроллером представления, освобождаются, но старые объекты все еще сохраняются в массиве предыдущего контроллера представления items .

(Я просто предполагаю. Если я ошибаюсь, было бы полезно, если бы вы объяснили, где вы сохраняете эти изображения.)

Комментарии:

1. Нет, это не массив изображений. Это массив URL-адресов изображений, просто NSStrings. Мне нужно провести некоторое исследование, у меня такое чувство, что это может быть вызвано каким-то сторонним кодом, который я использую.

2. Похоже, что это не контроллер просмотра, который сохраняет изображения. Если вы соответствующим образом освобождаете свойства в dealloc, единственный способ, которым я могу думать о том, что контроллер представления сохранит что-либо, — это использовать коллекцию, которая не копируется. Возможно, если вы посмотрите, где создаются или загружаются изображения, вы найдете, что на них держится.

Ответ №3:

Если вы «выталкиваете» представления на передний план, как это:

 infoScreen = [[[infoScreen alloc] initWithNibName:@"InfoScreen" bundle:nil] autorelease];
infoScreen.view.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
[self.view sendSubviewToBack:self.view];
  

Затем вы [infoScreen release];
должны освободить / освободить представление из памяти.
Помните все, что вам alloc нужно, или retain (есть и другие ситуации, но я забываю их сразу), которые вам нужны release .

Комментарии:

1. Я понимаю правила управления памятью. Я не уверен, что следую вашему предложению здесь.

2. возможно, я неправильно понял ваш вопрос, я подумал, что вам нужна помощь в освобождении памяти от viewcontrollers, которые больше не используются.

3. Мне кажется, что он удерживается в памяти, когда я извлекаю контроллер представления из стека.