Управление памятью вида при использовании NavigationController
Я изменил навигацию в своем приложении с UITabBarController на UINavigationController. Т.е. прежнее решение (1-я версия) было основано только на TabBarController - 4 ViewController (один простой TableView, один простой пользовательский вид и один MapView с множеством оверлеев). Вторая версия основана только на UINavigationController.
В случае TabBarController это было понятно и просто, все работало нормально, особенно MapView. Я имею в виду: MapView был загружен один раз (со значительным количеством наложений), и когда я перешел к другому представлению и вернулся к MapView, MapView все еще был там с уже загруженными и отображенными наложениями (простая проверка: вызывался viewDidLoad в MapView. только один раз за запуск приложения у меня там было несколько сообщений отладки).
Теперь я изменил логику навигации на UINavigationController. Все работает хорошо для первого взгляда - но: viewDidLoad (для каждого представления) вызывается каждый раз, когда я перехожу к представлению. Это раздражает, особенно в случае MapView - загрузка оверлеев выполняется каждый раз, это занимает некоторое время и в некоторых случаях вызывает сбой приложения.
ОК, мои вопросы:
Это какое-то "обычное" поведение NavigationController?
Могу ли я изменить это поведение, чтобы viewDidLoad вызывался только один раз?
И еще - Как я могу влиять на "последовательность отображения" некоторого представления?
Я понимаю, что логика, вероятно, более сложная, но я ценю любой ответ или подсказку;)
Некоторые связанные с этим обстоятельства:
- TabBar и навигационные контроллеры не совмещены.
- Я использую раскадровки, сегменты разрабатываются в UIB, в моем коде нет ручных вызовов, таких как perfomSegue или prepareForSegue. Одна кнопка запускает переход к MapView.
- Я использую push segues.
- Я также пытался использовать модальные сегменты, но без каких-либо изменений в этом поведении.
- любой из viewDidUnload никогда не вызывается во время переходов между представлениями.
- Предупреждение о памяти не получено.
- Нет утечек памяти, как на симуляторе, так и на iPhone 4.
- Я попытался создать очень простой временный проект / приложение, которое касается только Nav. Контроллер и другие виды без ЛЮБОГО кодирования, просто раскадровка. Это было то же самое поведение.
- Возникла проблема, которая вызывала сбой приложения, когда я быстро и периодически нажимал кнопку навигации и кнопку возврата между одним видом и MapView. В большинстве случаев приложение зависало, когда я нажимал кнопку "Назад" в MapView, прежде чем он был полностью отображен (т.е. его наложения). Это было исправлено, когда я добавил 1 сек. Задержка вызова метода в viewDidDisappeared в MapView. Это не честное решение, я знаю;)
1 ответ
UITabBarController
а также UINavigationController
основаны на принципиально разных парадигмах.
UITabBarController
предназначен для UIViewController
на каждой вкладке существуют независимо друг от друга и для пользователя, чтобы выбрать, что они хотят просмотреть. viewDidLoad
вызывается только один раз для каждого UIViewController
поскольку предполагается, что каждая вкладка все еще существует в памяти, даже когда пользователь переключается на другую вкладку.
UINavigationController
это стек UIViewControllers
где каждый связан с тем выше и ниже самого себя. Вершина UIViewController
в стеке всегда тот, который виден пользователю. Когда UIViewController
выталкивается в стек, его viewDidLoad
вызывается, потому что он загружается в память. Когда вершина UIViewController
извлекается из стека, выгружается из памяти и viewDidUnload
вызывается на выходе (viewDidUnload
устарела в iOS6 и не будет вызываться, но контроллер все равно будет выгружен из памяти). Вот почему viewDidLoad
вызывается каждый раз, когда пользователь нажимает UIViewController
на UINavigationController
стек.