#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. Мне кажется, что он удерживается в памяти, когда я извлекаю контроллер представления из стека.