Мне нужно выполнить некоторые действия, когда на навигационной панели нажата кнопка «Назад» (возврат к предыдущему экрану, возврат к родительскому виду).
Есть ли какой-нибудь метод, который я могу реализовать, чтобы перехватить событие и запустить некоторые действия, чтобы приостановить и сохранить данные до исчезновения экрана?
iphone
objective-c
ios
xcode
Ewok
источник
источник
Ответы:
ОБНОВЛЕНИЕ: Согласно некоторым комментариям, решение в первоначальном ответе, похоже, не работает при определенных сценариях в iOS 8+. Я не могу подтвердить, что это действительно так, без дальнейших подробностей.
Для тех из вас, однако, в этой ситуации есть альтернатива. Обнаружение, когда контроллер представления выталкивается, возможно путем переопределения
willMove(toParentViewController:)
. Основная идея заключается в том, что контроллер представления выталкивается, когда онparent
естьnil
.Проверьте "Реализация Контроллера Контейнера Представления" для получения дальнейшей информации.
Начиная с iOS 5 я обнаружил, что самый простой способ справиться с этой ситуацией - использовать новый метод
- (BOOL)isMovingFromParentViewController
:- (BOOL)isMovingFromParentViewController
имеет смысл, когда вы нажимаете и выталкиваете контроллеры в стеке навигации.Однако, если вы представляете контроллеры модального представления, вы должны использовать
- (BOOL)isBeingDismissed
вместо этого:Как отмечено в этом вопросе , вы можете объединить оба свойства:
Другие решения основаны на существовании
UINavigationBar
. Вместо этого мне больше нравится мой подход, потому что он отделяет требуемые задачи от действия, которое вызвало событие, то есть нажатие кнопки «назад».источник
self.isMovingFromParentViewController
имеет значение ИСТИНА, когда я загружаю стек навигации программно,popToRootViewControllerAnimated
без какого-либо прикосновения к кнопке возврата. Должен ли я снизить ваш ответ? (субъект говорит, что на навигационной панели нажата кнопка «назад»)override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParentViewController(){ println("back button pressed") } }
-viewDidDisappear:
так как вполне возможно , что вы получите-viewWillDisappear:
без-viewDidDisappear:
(например , когда вы начинаете ударяя отклонить элемент навигации контроллера , а затем отменить , что красть.Хотя
viewWillAppear()
иviewDidDisappear()
вызываются, когда нажата кнопка «Назад», они также вызываются в другое время. Смотрите конец ответа для более подробной информации.Использование UIViewController.parent
Обнаружение кнопки возврата лучше сделать, когда VC удален из родительского элемента (NavigationController) с помощью
willMoveToParentViewController(_:)
ИЛИdidMoveToParentViewController()
Если parent равен nil, контроллер представления извлекается из стека навигации и удаляется. Если parent не равен nil, он добавляется в стек и представляется.
Выгрузить
willMove
дляdidMove
и проверки self.parent сделать работу после того, как контроллер зрения уволен.Остановка увольнения
Обратите внимание, что проверка родителя не позволяет вам «приостановить» переход, если вам нужно выполнить какое-то асинхронное сохранение. Для этого вы можете реализовать следующее. Единственный недостаток - вы теряете красивую анимированную кнопку возврата в стиле iOS. Также будьте осторожны с интерактивным жестом. Используйте следующие для обработки этого случая.
Больше на вид будет / действительно появится
Если
viewWillAppear
viewDidDisappear
проблема не возникла, давайте рассмотрим пример. Скажем, у вас есть три контроллера вида:Давайте следовать звонки на ,
detailVC
как вы идете отlistVC
кsettingsVC
и обратноlistVC
Список> Детализация (push detailVC)
Detail.viewDidAppear
<- появляетсяДеталь> Настройки (push settingsVC)
Detail.viewDidDisappear
<- исчезаетИ как мы вернемся ...
Настройки> Подробно (всплывающие настройки ВК) <-
Detail.viewDidAppear
Появляютсяподробности> Список (всплывающие подробности ВК)
Detail.viewDidDisappear
<- исчезаютОбратите внимание, что
viewDidDisappear
вызывается несколько раз, не только при движении назад, но и при движении вперед. Для быстрой операции, которая может быть желательной, но для более сложной операции, такой как сетевой вызов, для сохранения, это может не сработать.источник
didMoveToParantViewController:
может выполнять работу, когда представление больше не видно. Полезно для iOS7 с интерактивным_ = self.navigationController?.popViewController(animated: true)
, поэтому оно вызывается не только нажатием кнопки «Назад». Я ищу звонок, который работает только при нажатии Назад.Первый метод
Второй метод
источник
Те, кто утверждает, что это не работает, ошибаются:
Это отлично работает. Так что же вызывает широко распространенный миф о том, что это не так?
Кажется, проблема связана с неправильной реализацией другого метода, а именно с тем, что реализация
willMove(toParent:)
забыла вызватьsuper
.Если вы реализуете
willMove(toParent:)
без вызоваsuper
, тоself.isMovingFromParent
будетfalse
и использованиеviewWillDisappear
будет не в состоянии. Это не подвело; ты сломал это.ПРИМЕЧАНИЕ . Настоящая проблема обычно заключается во втором контроллере вида, обнаружившем, что первый контроллер вида отключен. Пожалуйста, см. Также более общее обсуждение здесь: Unified UIViewController "стал самым передовым" обнаружением?
РЕДАКТИРОВАТЬ Комментарий предполагает, что это должно быть,
viewDidDisappear
а неviewWillDisappear
.источник
true
к интерактивному жесту смахивания пальцем - с левого края контроллера представления - даже если смахивание не выскочило полностью. Таким образом, вместо того, чтобы проверить этоwillDisappear
, делать это вdidDisappear
работе.Я играю (или борюсь) с этой проблемой в течение двух дней. IMO лучший подход - просто создать класс расширения и протокол, например так:
Это работает, потому что
UINavigationController
будет получать вызовnavigationBar:shouldPopItem:
каждый раз, когда контроллер представления подключен. Там мы обнаруживаем, была ли нажата спина или нет (любая другая кнопка). Единственное, что вам нужно сделать, это реализовать протокол в контроллере вида, где нажата кнопка назад.Не забудьте вручную вставить контроллер представления внутрь
backButtonPressedSel
, если все в порядке.Если у вас уже есть подклассы
UINavigationViewController
и реализованыnavigationBar:shouldPopItem:
, не волнуйтесь, это не помешает.Вы также можете быть заинтересованы в отключении жеста спины.
источник
Это работает для меня в iOS 9.3.x с Swift:
В отличие от других решений здесь, это, кажется, не срабатывает неожиданно.
источник
Для протокола, я думаю, что это больше того, что он искал ...
источник
Как
purrrminator
говорится, ответelitalon
не является полностью правильным, посколькуyour stuff
будет выполняться даже при программном вызове контроллера.Решение, которое я нашел до сих пор, не очень хорошее, но оно работает для меня. Помимо
elitalon
сказанного, я также проверяю, высовываю ли я программно или нет:Вы должны добавить это свойство к своему контроллеру и установить его в YES перед программным выводом:
Спасибо за вашу помощь!
источник
Лучший способ - использовать методы делегата UINavigationController.
Используя это, вы можете узнать, какой контроллер показывает UINavigationController.
источник
Я решил эту проблему, добавив UIControl к панели навигации с левой стороны.
И вам нужно помнить, чтобы удалить его, когда вид исчезнет:
Вот и все!
источник
Вы можете использовать обратный вызов кнопки «Назад», например:
для быстрой версии вы можете сделать что-то вроде в глобальной области видимости
Ниже того, что вы поместили в viewcontroller, где вы хотите контролировать действие кнопки назад:
источник
navigationShouldPopOnBackButton
? Он не является частью публичного API.Как сказал Coli88, вы должны проверить протокол UINavigationBarDelegate.
В более общем смысле вы также можете использовать пользовательскую
- (void)viewWillDisapear:(BOOL)animated
для выполнения пользовательской работы, когда представление, сохраняемое текущим видимым контроллером представления, собирается исчезнуть. К сожалению, это покрыло бы беспокоящие толчки и случаи популярности.источник
Для Swift с UINavigationController:
источник
Ответ 7ynk3r был очень близок к тому, что я использовал в конце, но для этого потребовались некоторые изменения:
источник
Вы должны проверить протокол UINavigationBarDelegate . В этом случае вам может потребоваться использовать навигационный бар: shouldPopItem: метод.
источник
self.navigationController.isMovingFromParentViewController больше не работает на iOS8 и 9, которые я использую:
источник
(СВИФТ)
окончательно найденное решение .. метод, который мы искали, будет "willShowViewController", который является методом делегата UINavigationController
источник
MyViewController
сPushedController
.