Подтвердить что ты не робот

UIViewController предотвращает просмотр с разгрузки

Когда мое приложение iPhone получает предупреждение о том, что просмотры UIViewControllers, которые в настоящее время не видны, выгружаются. В одном конкретном контроллере выгрузка вида и выходов довольно смертельна.

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

Я вижу, что UIViewController имеет метод unloadViewIfReloadable, который вызывается при появлении предупреждения о памяти. Кто-нибудь знает, как сказать Cocoa Коснитесь, что мое представление не перезагружается?

Любые другие рекомендации по предотвращению выгрузки моего представления из памяти в память?

Заранее спасибо


В документах Apple о жизненном цикле просмотра контроллера просмотра говорится:

didReceiveMemoryWarning - По умолчанию реализация высвобождает только представление если он определяет, что это безопасно делать так

Теперь... Я переопределяю didReceiveMemoryWarning с пустой функцией, которая просто вызывает NSLog, чтобы сообщить мне, что было получено предупреждение. Однако - просмотр все равно разгружается. Плюс, по какому критерию точно решено, безопасно ли выгрузить разбух... о! так много вопросов!

4b9b3361

Ответ 1

Что, по-видимому, работает для меня, это переопределить setView:, чтобы игнорировать параметр в nil. Это kludgy, но тогда, это проблема kludgy, и это сделало трюк:

-(void)setView:(UIView*)view {
    if(view != nil || self.okayToUnloadView) {
        [super setView:view];
    }
}

Ответ 2

В соответствии с документами реализация по умолчанию didReceiveMemoryWarning: освобождает представление, если это безопасно (т.е.: superview == nil),

Чтобы предотвратить публикацию представления, вы можете переопределить didReceiveMemoryWarning: но в вашей реализации не вызывайте [super didReceiveMemoryWarning]. То, что представление выпущено по умолчанию (если не видно).

По умолчанию didReceiveMemoryWarning освобождает представление, вызывая [viewcontroller setView:nil], поэтому вместо этого вы можете переопределить его.

Ответ 3

Неужели это так просто?

Несмотря на то, что нигде в документации это не упоминается, кажется, что если я исключительно сохраняю свой вид в viewDidLoad, он не будет выпущен в Memory Warning. Я пробовал с несколькими последовательными предупреждениями в симуляторе, и все они кажутся хорошими.

Итак... трюк на данный момент - "сохранить" в viewDidLoad и релиз в dealloc - таким образом, viewcontroller "застревает" с представлением до момента его освобождения.

Я проведу еще немного и напишу о результатах

Ответ 4

Я не думаю, что любая из этих идей работает. Я попытался переопределить [didReceiveMemoryWarning], и это сработало для некоторых телефонов, но обнаружил, что один телефон выгрузил представление ПЕРЕД тем, что этот метод был даже вызван (должен был быть в крайне низкой памяти или что-то в этом роде). Переопределение [setView] создает множество предупреждений о регистрации журналов, поэтому я не буду рисковать Apple. Сохранение вида просто приведет к утечке этого вида - это предотвратит сбои, но не работает - представление будет заменено в следующий раз при загрузке пользовательского интерфейса контроллера.

Итак, вы просто должны планировать, что ваши взгляды разгружаются в любое время, когда они за пределами экрана, что не идеально, но вы идете. Лучшие образцы, которые я нашел для работы с этим, - это немедленная фиксация, поэтому ваш пользовательский интерфейс всегда обновляется или копирует-редактирует-копирует, где вы копируете свою модель во временный экземпляр, заполняете свои представления и используете немедленную фиксацию с помощью этот экземпляр, затем скопируйте изменения обратно в исходную модель, когда пользователь нажимает "сохранить" или что-то еще.

Ответ 5

Поскольку принятое решение имеет проблемы с тем, что viewDidUnload все еще вызывается, даже если представление было заблокировано от очистки, я использую другой, хотя все еще хрупкий подход. Система выгружает представление с помощью сообщения unloadViewForced: для контроллера, поэтому я перехватываю это, чтобы заблокировать сообщение. Это предотвратит путаный вызов viewDidUnload. Здесь код:

@interface UIViewController (Private)
- (void)unloadViewForced:(BOOL)forced;
@end

- (void)unloadViewForced:(BOOL)forced {
    if (!_safeToUnloadView) {
        return;
    }
    [super unloadViewForced:forced];
}

У этого есть очевидные проблемы, поскольку он перехватывает недокументированное сообщение в UIViewController.

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