Метод viewWillDisappear не сохраняет данные

xcode

#1

подскажите, в чем специфика этого метода? Ситуация такая - пытаюсь вызвать в нем метод для сохранения изменений, например, после удаления элемента из таблицы в табл вью контроллере. Но при переходе с помощью таб бара на другой табл вью контроллер, где стоит пикер вью, который отображает элементы таблицы первого табл вью контролера, это удаление в нем сразу не отображается. Пикер вью по-прежнему показывает удаленный элемент. Потом, когда покликаешь туда сюда, то удаленный элемент исчезает, но вот при первом переходе ( не didLoad) он висит. И что характерно, если вызываю тот же самый метод сохранения изменений в другом месте, там, где удаляется элемент из таблицы, то пикер вью показывает все как надо сразу. Т.е. получается, все одинаково, отличается только место вызова метода сохранения изменений. Если он вызывается с помощью viewWillDisappear, то удаление сразу не отображается на пикер вью во втором табл вью контролере.

Подозреваю, что это как-то связано с иерархией табл вью контроллеров, но как? Документация только упоминает об этом без подробностей.


#2

Все rootController’ы от TabBarController’a не вызывают метод Disappear при переключении между rootController’ами. Они всегда остаются в памяти.
Для вашего случая, вы можете из первого rootController’a получить свой TabBarController, из него по индексу получить rootController номер 2 и вызвать к примеру у него метод для обновления данных в pickerView.


#3

Вау! Вот это да. Спасибо за подсказку.

Т.е. получается, что и viewVillAppear метод у них тоже не работает?


#4

Да, все верно. Но это при условии, что вы переключаетесь между rootController’ами.


#5

Но как тогда объяснить, что второе переключение между рутконтроллерами все-таки меняет данные во втором рутконтроллере?


#6

Попробуйте посмотреть принт в этих методах. Так будет намного нагляднее.


#7

да, надо посмотреть. Я уже однажды так делал, только не обращал внимание на разные типы переходов. Пошел пробовать.

Забегая вперед, а есть ли какие-то другие стандартные методы, чтобы обновлять данные при переключении между рутконтроллерами? Или все-таки надо писать свой updateView?


#8

Как я уже написал выше, это первый метод.
Второй метод через нотификации.


#9

Спасибо за подсказку направления.

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


#10

Боюсь вы сильно ошибаетесь, почитайте про жизненный цикл vc:


#11

Мне тоже кажется, что viewWillAppear срабатывает каждый раз, при показе контроллера. Я там обновляю данные у вкладок ТабБара, которые нужно обновлять при каждом показе - всё вроде работает…


#12

Вот это я знатно лажанул. Maxim извиняюсь.

@haymob про жизненный цикл я читал, но именно для rootController’ов таббара мне казалось они не вызываются, т.к. они всегда остаются открытыми из-за того, что они при загрузке табтара загружаются в память все разом.
И тогда к вашим тестам один вопрос: что у вас будет, если нажать на 1 таб 2 раза?


#13

NavigationController перейдет на root, если он уже на root то ничего не будет.


#14

Загружаются при первом открытии. Точнее viewDidLoad срабатывает при первом открытии, классы сразу инициализируются.


#15

Меня все это время не покидало ощущение, что я не с проста так лоханулся.
Как оказалось, такое поведение существует на Андроиде. При переключении между фрагментами таббара, у них не вызывается метод onResume. Правда тут есть нюанс, если мы перейдем из любого фрагмента таббара по иерархие выше (откроем Активити), то при возврате метод onResume сработает у всех фрагментов таббара.

Будем считать, что я частично оправдался :slight_smile: Несколько проектов на обе платформы висят, часто переключаюсь с платформы на платформу и часто путаю уже между ними некоторые детали работы.


#16

думаю вы не совсем ошиблись. Я тоже вчера ночью потестировал и вот что получилось. Во-первых, да, действительно, методы view…Appear все-таки работают при использовании того же Tab Bar. Но вот во-вторых, там получается интересная картинка.

Это принты первого перехода с первого TVC на второй:

This is a viewWillDisappear method in TVC1
This is a viewDidLoad method in TVC2
This is viewWillAppear method in TVC2

Т.е. здесь все чин чинарем как и положено, методы идут один за одним.

А теперь что происходит на втором переходе, т.е. когда приложение не закрывается, а юзер просто переключается на первый TVC, а потом снова идет на второй.

This is viewWillAppear method in TVC2
This is a viewWillDisappear method in TVC1

Здесь получается, что viewWillAppear method in TVC2 отрабатывает раньше, чем viewWillDisappear method in TVC1. Если это так, то тогда все логично объясняется. Тогда получается, что второй TVC открывается быстрее, чем закрывается первый и поэтому понятно, почему второй не показывает изменения, которые сделаны в первом.

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

И заодно уже, чтобы два раза не вставать, я проверил передаются ли данные по изменениям при самом первом заходе на второй TVC, т.е. когда юзер открыл приложение на первом TVC, удаляет здесь элемент и после этого, переходит на второй TVC. Как и ожидалось, в этом случае, изменения передаются! Потому как методы идут последовательно - см выше, первая часть принтов. А вот если потом переключаться между табами, то там уже последовательность другая и получается вся эта картинка с не передачей изменений.


#17

Способы решения уже были выше, так что победить это вы знаете как.
С методом Disappear я не проверял последовательность вызовов, тут пока сказать ничего не могу.


#18

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

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


#19

А могли бы вы показать код из вашей гифки? Хочу посмотреть как запускаются все эти методы в тестовом режиме.


#20

Там нет никакого кода, просто принты в методах.