Восстановление состояния в панели вкладок и в приложении Navigation Controller
Цель: я пытаюсь восстановить состояние приложения на основе контроллера вкладок (с контроллерами навигации на каждой вкладке).
Проблема: При повторном запуске выбранная вкладка, кажется, восстанавливается, как и ожидалось, но иерархия навигации внутри указанной вкладки - нет.
Разработка:
- Я впервые начал с шаблона проекта "Приложение на основе вкладок".
- Затем я добавил идентификаторы восстановления для обоих дочерних контроллеров представления и контроллера панели вкладок.
- В приложении делегат я реализовал
application(_:shouldSaveApplicationState:)
а такжеapplication(_:shouldRestoreApplicationState:)
,
Затем я запускаю приложение, переключаюсь на вторую (правую) вкладку, нажимаю home, завершаю работу. o перезапуск, отображается правая вкладка (как и ожидалось). Все идет нормально.
- Затем я перехожу к раскадровке и встраиваю оба дочерних контроллера представления в соответствующие контроллеры навигации, и назначаю им идентификаторы восстановления.
Я запускаю приложение, и восстановление все еще работает. Все еще хорош.
Затем я добавляю "детальный" вид контроллера; его класс является пользовательским подклассом
UIViewController
к раскадровке со свойствами для настройки содержимого метки отладки и цвета фона его представления.Я поместил кнопку "Показать детали..." на каждом из контроллеров вида сверху вкладок и создал переход от каждого в (общий) контроллер представления детали. Так что теперь моя раскадровка выглядит как шестиугольник (также у обоих сегментов есть идентификаторы, установленные в Интерфейсном Разработчике). Таким образом, и левый, и правый контроллеры вида сверху используют один и тот же тип "детального" контроллера вида. На показе это настроено так, чтобы отличить от того, где это было выдвинуто (см. Следующий пункт).
На каждом из контроллеров вида сверху
prepareForSegue(_:sender:)
Метод, я настраиваю контроллер представления подробного толкания по-разному: различные цвета текста и фона ("левый" и синий, и "правый" и красный, соответственно).Я добавил код в контроллер подробного представления, чтобы сохранить и восстановить состояние свойств текста и цвета фона:
encodeRestorableStateWithCoder(_:)
а такжеdecodeRestorableStateWithCoder(_:)
, Также я реализовалviewDidLoad()
чтобы отразить значения этих свойств в представлении. Всякий раз, когда он создается и передается в навигацию через переход, свойства сначала устанавливаются, а затем используются для настройки представления вviewDidLoad()
, Всякий раз, когда он создается во время восстановления, свойства устанавливаются вdecodeRestorableStateWithCoder(_:)
и так же используется вviewDidLoad()
,
... но когда я запускаю этот код, последняя выбранная вкладка восстанавливается, но только до контроллера вида сверху - слева или справа, а не детали. Интересно, что цвет фона, последний установленный для контроллера детального вида, мигает на мгновение.
Я поместил точки останова в encodeRestorableStateWithCoder(_:)
а также decodeRestorableStateWithCoder(_:)
, но только первый из них выполняется (кодировать).
- Задумываясь о том, что может отсутствовать, я пошел дальше и реализовал приложение делегата
application(_:viewControllerWithRestorationIdentifierPath:coder:)
(возвращает всегда ноль, но протоколирование пройденных компонентов пути).
В документации не очень ясно, нужен ли этот метод или нет, и в любом случае все контроллеры представления, кроме детали, кажутся восстановленными идеально даже без него. Я добавил код для создания экземпляра каждого контроллера представления на основе последнего компонента пути (т. Е. Идентификатора восстановления этого контроллера) и его возврата.
Теперь decodeRestorableStateWithCoder(_:)
вызывается, но навигация все еще возвращается к контроллеру вида сверху вкладки через доли секунды.
Так, что происходит? Чего мне не хватает для реализации сохранения и восстановления состояния в приложении панели вкладок + контроллера навигации?
1 ответ
ИСПРАВЛЕНО: Итак, с моим кодом было несколько проблем...
Оказывается, в моем случае мне не нужно реализовывать
application(_:viewControllerWithRestorationIdentifierPath:coder:)
, (см. комментарии к этому ответу)Мои реализации
encodeRestorableStateWithCoder(_:)
а такжеdecodeRestorableStateWithCoder(_:)
не звонилиsuper
(как предложено в принятом ответе на вопрос выше).наконец, у меня появился нужный контроллер представления (деталь), но состояние его подпредставлений (содержимое текстовой метки и цвет фона основного вида) было в исходном пустом состоянии (не восстанавливается до своего последнего состояния -ie, содержимое текстовой метки) и цвет бг). Как уже упоминалось в этом вопросе, viewDidLoad() не вызывается сразу после
decodeRestorableStateWithCoder(_:)
(как я и предполагал), поэтому вместо этого я вызываю общий метод из обоихviewDidLoad()
а такжеdecodeRestorableStateWithCoder(_:)
обновить пользовательский интерфейс.
Как обычно, я поспешил опубликовать вопрос, прежде чем искать или пробовать достаточно модификаций в моем коде (мои извинения...).
Я надеюсь, что это по крайней мере помогает кому-то еще.
Как обычно, я подожду пару дней, прежде чем принять свой собственный ответ, на случай, если кто-то прольет дополнительный свет.