Я читал многочисленные сообщения о людях , имеющих проблемы с , viewWillAppear
когда вы не создаете иерархию вида только права. Моя проблема в том, что я не могу понять, что это значит.
Если я создам RootViewController
и вызываю addSubView
этот контроллер, я ожидаю, что добавленные представления будут подключены к viewWillAppear
событиям.
Есть ли у кого-нибудь пример сложной программной иерархии представлений, которая успешно принимает viewWillAppear
события на каждом уровне?
В Документах Apple говорится:
Предупреждение: если представление, принадлежащее контроллеру представления, добавляется в иерархию представления напрямую, контроллер представления не получит это сообщение. Если вы вставляете или добавляете представление в иерархию представлений, и у него есть контроллер представления, вы должны отправить это сообщение напрямую связанному контроллеру представления. Если не отправить контроллер представления, это сообщение предотвратит отображение любой связанной анимации.
Проблема в том, что они не описывают, как это сделать. Что значит «прямо»? Как вы «косвенно» добавляете представление?
Я новичок в Cocoa и iPhone, поэтому было бы неплохо, если бы помимо основной хрени Hello World были полезные примеры от Apple.
источник
Ответы:
Если вы используете контроллер навигации и устанавливаете его делегата, то методы view {Will, Did} {Appear, Disappear} не вызываются.
Вместо этого вам нужно использовать методы делегата контроллера навигации:
источник
Я столкнулся с той же проблемой. Просто отправьте
viewWillAppear
сообщение своему контроллеру представления, прежде чем добавлять его в качестве подпредставления. (Есть один параметр BOOL, который сообщает контроллеру представления, появляется ли он в анимации или нет.)Посмотрите на RootViewController.m в примере с Metronome.
(На самом деле я нашел примеры проектов Apple великолепными. Их НАМНОГО больше, чем HelloWorld;)
источник
[scrollView addSubview:controller.view];
.[controller viewWillAppear:NO];
Потом я добавил строчку и вуаля! Работал как шарм.Я наконец нашел решение, ЧТО РАБОТАЕТ!
UINavigationControllerDelegate
Я думаю, что суть этого заключается в том, чтобы установить делегата вашего навигационного элемента управления на контроллер представления, в котором он находится, и реализовать
UINavigationControllerDelegate
и это два метода. Brilliant! Я так взволнован, что наконец нашел решение!источник
У меня была такая же проблема. В моем приложении у меня есть 2 контроллера навигации, и нажатие одного и того же контроллера представления в каждом из них сработало в одном случае, а не в другом. Я имею в виду , что при нажатии на тот же контроллер представления в первом
UINavigationController
,viewWillAppear
был вызван , но не тогда , когда нажат второй навигации контроллера.Затем я наткнулся на этот пост UINavigationController должен вызывать методы viewWillAppear / viewWillDisappear
И понял, что мой второй контроллер навигации действительно переопределил
viewWillAppear
. Проверка кода показала, что я не звонюЯ добавил, и все заработало!
В документации говорится:
источник
Я пользуюсь контроллером навигации. Когда я хочу либо перейти на другой уровень данных, либо показать свое собственное представление, я использую следующее:
Когда я это делаю,
viewWillAppear
функция срабатывает. Я полагаю, это квалифицируется как «косвенный», потому что я сам не вызываю фактическийaddSubView
метод. Я не знаю, применимо ли это на 100% к вашему приложению, поскольку я не могу сказать, используете ли вы контроллер навигации, но, возможно, он даст подсказку.источник
Спасибо, iOS 13.
Кредиты идут Ареку Холко . Он действительно спас мне день.
источник
Во-первых, панель вкладок должна находиться на корневом уровне, то есть добавляться к окну, как указано в документации Apple. Это ключ к правильному поведению.
Во-вторых, вы можете использовать
UITabBarDelegate
/UINavigationBarDelegate
для пересылки уведомлений вручную, но я обнаружил, что для правильной работы всей иерархии вызовов представления все, что мне нужно было сделать, это вручную вызватьи
.. только ОДИН РАЗ перед настройкой контроллеров представления на соответствующем контроллере (сразу после выделения). С этого момента он правильно вызывал эти методы на своих дочерних контроллерах представления.
Моя иерархия такая:
Просто вызов упомянутых методов на контроллере tab / nav в первый раз гарантирует, что ВСЕ события были перенаправлены правильно. Это избавило меня от необходимости вызывать их вручную из
UINavigationBarDelegate
/UITabBarControllerDelegate
методов.Примечание: любопытно, что когда это не сработало, частный метод
.. который вы можете видеть из стека вызовов на работающей реализации, обычно вызывает
viewWill/Did..
методы, но не делал этого до тех пор, пока я не выполнил вышеуказанное (даже если он был вызван).Я думаю, что ОЧЕНЬ важно, чтобы
UITabBarController
это было на уровне окна, и документы, похоже, подтверждают это.Надеюсь, что это было ясно (иш), рад ответить на дальнейшие вопросы.
источник
Поскольку ответ не принимается и люди (как и я) приземляются здесь, я даю свой вариант. Хотя я не уверен, что это была изначальная проблема. Когда контроллер навигации добавляется в качестве подпредставления к другому представлению, вы должны сами вызвать методы viewWillAppear / Dissappear и т. Д. Следующим образом:
Просто чтобы сделать пример законченным. Этот код появляется в моем ViewController, где я создал и добавил контроллер навигации в представление, которое я поместил в представление.
.h выглядит так
В файле пера у меня есть представление, а под ним - метка с изображением и контейнером (другое представление), куда я вставляю контроллер. Вот как это выглядит. Мне пришлось кое-что перемешать, так как это была работа для клиента.
источник
Просмотры добавляются "напрямую" по телефону
[view addSubview:subview]
. Представления добавляются «косвенно» такими методами, как панели вкладок или панели навигации, которые меняют подвиды.Каждый раз, когда вы звоните
[view addSubview:subviewController.view]
, вы должны звонить[subviewController viewWillAppear:NO]
(или ДА, в зависимости от вашего случая).У меня возникла эта проблема, когда я реализовал свою собственную систему управления корневым представлением для подэкрана в игре. Добавление вызова к viewWillAppear вручную устранило мою проблему.
источник
Правильный способ сделать это - использовать api контейнера UIViewController.
источник
viewWillAppear:
еще может не называтьсяЯ использую этот код для контроллеров push и pop view:
От себя:
поп:
.. и он отлично работает у меня.
источник
Очень распространенная ошибка заключается в следующем. У вас есть один вид,
UIView* a
и еще один,UIView* b
. Вы добавляете b в a как подвид. Если вы попытаетесь вызвать viewWillAppear в b, он никогда не будет запущен, потому что это подпредставлениеисточник
iOS 13 воткнула мое приложение в зад. Если вы заметили изменение поведения в iOS 13, просто установите следующее, прежде чем нажимать:
Вам также может потребоваться установить его в своем .storyboard в инспекторе атрибутов (установите для параметра «Презентация» значение «Полный экран»).
Это заставит ваше приложение вести себя так же, как в предыдущих версиях iOS.
источник
Я не уверен в этом на 100%, но я думаю, что добавление представления в иерархию представлений напрямую означает вызов
-addSubview:
представления контроллера представления (например,[viewController.view addSubview:anotherViewController.view]
) вместо того, чтобы помещать новый контроллер представления в стек контроллера навигации.источник
Я думаю, что добавление подпредставления не обязательно означает, что представление появится, поэтому нет автоматического вызова метода класса, который
источник
Я думаю, что они имеют в виду «напрямую», соединяя вещи точно так же, как это делает шаблон xcode «Navigation Application», который устанавливает UINavigationController в качестве единственного подвида UIWindow приложения.
Использование этого шаблона - единственный способ получить методы Will / Did / Appear / Disappear, вызываемые в объекте ViewControllers при push / pop этих контроллеров в UINavigationController. Ни одно из других решений в ответах здесь не помогло мне, включая их реализацию в RootController и передачу их (дочернему) NavigationController. Эти функции (будут / появятся / появятся / исчезнут) вызывались только в моем RootController при отображении / скрытии VC верхнего уровня, моего "входа" и навигационных VC, а не суб-VC в контроллере навигации, поэтому у меня не было возможности "передать их" в Nav VC.
Я закончил тем, что использовал функциональность делегата UINavigationController для поиска конкретных переходов, которые требовали последующей функциональности в моем приложении, и это работает, но требует немного больше работы, чтобы «смоделировать» функциональность как исчезновения, так и появления.
Также это вопрос принципа - заставить его работать после того, как я часами бился головой об этой проблеме сегодня. Мы будем очень благодарны за любые рабочие фрагменты кода, использующие настраиваемый RootController и дочерний навигационный VC.
источник
Если это кому-то поможет. У меня была аналогичная проблема, когда мой
ViewWillAppear
не стрелял изUITableViewController
. После долгой игры я понял, что проблема в том,UINavigationController
что управляющий myUITableView
не находится в корневом представлении. Как только я исправлю это, теперь он работает как чемпион.источник
У меня только что была эта проблема, и мне потребовалось 3 полных часа (2 из которых - поиск в Google), чтобы исправить ее.
Оказалось, что помогло просто удалить приложение с устройства / симулятора, очистить и снова запустить. .
надеюсь, это поможет
источник
Установите делегата на контроллер корневого представления.
источник
Для Свифта. Сначала создайте протокол для вызова того, что вы хотите вызвать, в viewWillAppear
Во-вторых, создайте класс
}
В-третьих, сделайте экземпляр ForceUpdateOnViewAppear членом соответствующего класса, который имеет доступ к контроллеру навигации и существует, пока существует контроллер навигации. Это может быть, например, корневой контроллер представления контроллера навигации или класс, который его создает или представляет. Затем как можно раньше назначьте экземпляр ForceUpdateOnViewAppear свойству делегата контроллера навигации.
источник
В моем случае проблема заключалась в пользовательской анимации перехода. При установке
modalPresentationStyle = .custom
viewWillAppear
не вызываетсяв настраиваемом классе анимации перехода нужны методы вызова:
beginAppearanceTransition
иendAppearanceTransition
источник
В моем случае это была просто странная ошибка в эмуляторе ios 12.1. Исчез после запуска на реальном устройстве.
источник
Я создал класс, решающий эту проблему. Просто установите его как делегата вашего контроллера навигации и реализуйте один или два простых метода в вашем контроллере представления, которые будут вызываться, когда представление будет показано или было показано через NavigationController.
Вот GIST, показывающий код
источник
ViewWillAppear - это метод переопределения класса UIViewController, поэтому добавление subView не вызовет viewWillAppear, но когда вы представляете, нажимаете, выталкиваете, показываете, setFront или popToRootViewController из viewController, тогда вызывается viewWillAppear для представленного viewController.
источник
Моя проблема заключалась в том, что viewWillAppear не вызывался при раскручивании из перехода. Ответ заключался в том, чтобы вызвать viewWillAppear (true) в сегменте раскрутки в контроллере представления, к которому вы возвращаетесь.
@IBAction func unwind (для unwindSegue: UIStoryboardSegue, ViewController followingVC: Any) {
источник
Не уверен, что это та же проблема, которую я решил.
В некоторых случаях метод не выполняется обычным способом, например "[self methodOne]".
Пытаться
источник
viewWillAppear
не называется вообщеУ вас должен быть активен только 1 UIViewController в любое время. Любые подпредставления, которыми вы хотите манипулировать, должны быть именно такими - subVIEWS - то есть UIView.
Я использую простую технику для управления своей иерархией представлений, и с тех пор, как я начал это делать, я еще не столкнулся с проблемой. Есть 2 ключевых момента:
Что я имею в виду под "стоимостью экрана"? Это намеренно немного расплывчато, но обычно это функция или раздел вашего приложения. Если у вас есть несколько экранов с одинаковым фоновым изображением, но с разными наложениями / всплывающими окнами и т. Д., Это должен быть 1 контроллер представления и несколько дочерних представлений. Вы никогда не должны работать с двумя контроллерами представления. Обратите внимание, что вы все равно можете создать экземпляр UIView в одном контроллере представления и добавить его в качестве подпредставления другого контроллера представления, если вы хотите, чтобы определенные области экрана отображались в нескольких контроллерах представления.
Что касается UINavigationController - это ваш лучший друг! Отключите панель навигации и укажите НЕТ для анимации, и вы получите отличный способ переключения экранов по запросу. Вы можете нажимать и открывать контроллеры представления, если они находятся в иерархии, или вы можете подготовить массив контроллеров представления (включая массив, содержащий один VC) и установить его как стек представления с помощью setViewControllers. Это дает вам полную свободу изменять VC, получая при этом все преимущества работы в рамках ожидаемой модели Apple и правильного запуска всех событий и т. Д.
Вот что я делаю каждый раз, когда запускаю приложение:
(примечание, что начинать с оконного типа - это просто личное предпочтение - мне нравится конструировать вещи самостоятельно, поэтому я точно знаю, как они построены. Он должен работать нормально с шаблоном на основе представления)
Все события запускаются правильно, и в основном жизнь хороша. Затем вы можете потратить все свое время на написание важных частей своего приложения и не возиться с попытками вручную преобразовать иерархии представлений в форму.
источник