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

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

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

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

Хорошо, мои вопросы:

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

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

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

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

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

  • Контроллеры TabBar и Navigation не объединены.
  • Я использую раскадровки, переходы создаются в UIB, в моем коде нет ручных вызовов, таких как perfomSegue или prepareForSegue. Одна кнопка вызывает переход к MapView.
  • Я использую push segues.
  • Я также пытался использовать модальные переходы, но без каких-либо изменений в этом поведении.
  • any из viewDidUnload никогда не вызывается во время переходов между представлениями.
  • Предупреждение о памяти не получено.
  • Как на симуляторе, так и на iPhone 4 утечек памяти не зафиксировано.
  • Я попытался создать очень простой временный проект / приложение, которое касается только Nav. Контроллер и другие представления без ЛЮБОГО кодирования, только раскадровка. Было такое же поведение.
  • Возникла проблема, приводившая к сбою приложения, когда я быстро и периодически нажимал кнопку навигации и кнопку возврата между одним представлением и MapView. В большинстве случаев приложение вылетало, когда я нажимал кнопку «Назад» в MapView до того, как оно было полностью отображено (т.е. его наложения). Это было исправлено, когда я добавил 1 сек. вызов метода delay в viewDidDisappeared в MapView. Я знаю, что это несправедливо;)

person Vitek    schedule 09.03.2013    source источник
comment
перед выделением класса карты при нажатии его на контроллер навигации проверьте, является ли его значение nil, если nil, затем выделите его, иначе напрямую нажмите класс карты на контроллер навигации.   -  person prasad    schedule 09.03.2013


Ответы (1)


UITabBarController и UINavigationController основаны на принципиально разных парадигмах.

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

UINavigationController - это стопка UIViewControllers, каждая из которых связана с предыдущей и нижней. Верхний UIViewController в стеке всегда виден пользователю. Когда UIViewController помещается в стек, вызывается его viewDidLoad, потому что он загружается в память. Когда верхние UIViewControllergets извлекаются из стека, они выгружаются из памяти, а viewDidUnload вызывается при выходе (viewDidUnload устарел в iOS6 и не будет вызываться, но контроллер все равно будет выгружен из памяти). Вот почему viewDidLoad вызывается каждый раз, когда пользователь помещает конкретный UIViewController в стек UINavigationController.

person Jeff Wolski    schedule 09.03.2013
comment
У вас опечатка - -viewDidUnload устарела в ios6, а не -viewDidLoad - person Rich Tolley; 09.03.2013
comment
Хороший улов! Исправлено сейчас. Спасибо. - person Jeff Wolski; 09.03.2013
comment
и viewDidUnload вызывается при выходе Нет, не будет, в версиях до iOS 6. viewDidUnload вызывается только тогда, когда представление выгружается. Представление выгружается только при нехватке памяти. В 99% случаев вы никогда не увидите выгружаемых просмотров. - person newacct; 10.03.2013