Управление памятью вида при использовании NavigationController

Я изменил навигацию в своем приложении с UITabBarController на UINavigationController. Т.е. прежнее решение (1-я версия) было основано только на TabBarController - 4 ViewController (один простой TableView, один простой пользовательский вид и один MapView с множеством оверлеев). Вторая версия основана только на UINavigationController.

В случае TabBarController это было понятно и просто, все работало нормально, особенно MapView. Я имею в виду: MapView был загружен один раз (со значительным количеством наложений), и когда я перешел к другому представлению и вернулся к MapView, MapView все еще был там с уже загруженными и отображенными наложениями (простая проверка: вызывался viewDidLoad в MapView. только один раз за запуск приложения у меня там было несколько сообщений отладки).

Теперь я изменил логику навигации на UINavigationController. Все работает хорошо для первого взгляда - но: viewDidLoad (для каждого представления) вызывается каждый раз, когда я перехожу к представлению. Это раздражает, особенно в случае MapView - загрузка оверлеев выполняется каждый раз, это занимает некоторое время и в некоторых случаях вызывает сбой приложения.

ОК, мои вопросы:

  1. Это какое-то "обычное" поведение NavigationController?

  2. Могу ли я изменить это поведение, чтобы viewDidLoad вызывался только один раз?

  3. И еще - Как я могу влиять на "последовательность отображения" некоторого представления?

Я понимаю, что логика, вероятно, более сложная, но я ценю любой ответ или подсказку;)

Некоторые связанные с этим обстоятельства:

  • 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 стек.

Другие вопросы по тегам