Я пытаюсь переписать действие по умолчанию кнопки «Назад» в контроллере навигации. Я предоставил цели действие на пользовательской кнопке. Странно то, что при назначении его через атрибут backbutton он не обращает на них внимания, а просто выскакивает из текущего представления и возвращается к корню:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: @"Servers"
style:UIBarButtonItemStylePlain
target:self
action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;
Как только я установил его через leftBarButtonItem
on, navigationItem
он вызывает мое действие, но кнопка выглядит как круглая, а не как стрелка назад:
self.navigationItem.leftBarButtonItem = backButton;
Как я могу заставить его вызывать свое пользовательское действие, прежде чем вернуться к корневому представлению? Есть ли способ перезаписать обратное действие по умолчанию, или есть метод, который всегда вызывается при выходе из представления ( viewDidUnload
не делает этого)?
Ответы:
Попробуйте вставить это в контроллер вида, где вы хотите обнаружить нажатие:
источник
if (find(self.navigationController!.viewControllers as! [UIViewController],self)==nil)
Я реализовал расширение UIViewController-BackButtonHandler . Для этого не нужно создавать подклассы, просто поместите это в свой проект и переопределите
navigationShouldPopOnBackButton
метод вUIViewController
классе:Загрузите пример приложения .
источник
navigationBar:shouldPopItem:
не приватный метод, поскольку он является частьюUINavigationBarDelegate
протокола.YES
)? или это будет в будущем? подклассы, вероятно, более безопасный вариантNO
кнопка возврата остается в отключенном состоянии (визуально, потому что она все еще получает и реагирует на сенсорные события). Я обошел его, добавивelse
оператор кshouldPop
проверке и циклически просматривая подпредставления навигационной панели, и установивalpha
значение обратно на 1, если это необходимо, внутри блока анимации: gist.github.com/idevsoftware/9754057В отличие от Амаграммера, это возможно. Вы должны подкласс вашего
navigationController
. Я все объяснил здесь (включая пример кода).источник
Swift версия:
(из https://stackoverflow.com/a/19132881/826435 )
В вашем контроллере представления вы просто соблюдаете протокол и выполняете все необходимые действия:
Затем создайте класс, скажем
NavigationController+BackButton
, и просто скопируйте и вставьте код ниже:источник
shouldPopOnBackButtonPress
должен вызываться, пока нет ошибок.performSomeActionOnThePressOfABackButton
это просто выдуманный метод, который не существует.performSomeActionOnThePressOfABackButton
в моем контроллере для выполнения определенного действия при нажатии кнопки «Назад», но этот метод никогда не вызывался, действие является нормальным возвратом назадUINavigationController
,navigationBar.delegate
установлен на контроллер навигации. Так что методы ДОЛЖНЫ быть вызваны. Однако в Swift я не могу заставить их вызываться даже в подклассе. Однако я сделал так, чтобы они вызывались в Objective-C, поэтому сейчас я просто использую версию Objective-C. Может быть, Быстрая ошибка.Это невозможно сделать напрямую. Есть пара альтернатив:
UIBarButtonItem
который проверяется при нажатии и появляется, если тест пройденUITextField
метода делегата, например-textFieldShouldReturn:
, который вызывается после нажатия кнопкиReturn
илиDone
на клавиатуре.Недостатком первого варианта является то, что стиль стрелки влево на кнопке «Назад» не может быть доступен с помощью пользовательской кнопки панели. Таким образом, вы должны использовать изображение или перейти с обычной кнопки стиля.
Второй вариант удобен тем, что вы возвращаете текстовое поле в методе делегата, поэтому вы можете настроить свою логику проверки на конкретное текстовое поле, отправленное методу обратного вызова делегата.
источник
По некоторым причинам многопоточности решение, упомянутое @HansPinckaers, мне не подошло, но я нашел очень простой способ поймать прикосновение к кнопке «Назад», и я хочу закрепить это здесь на случай, если это поможет избежать многочасовых обманов кто-то еще. Трюк действительно прост: просто добавьте прозрачную UIButton в качестве подпредставления к вашему UINavigationBar, и установите ваши селекторы для него, как если бы это была настоящая кнопка! Вот пример, использующий Monotouch и C #, но перевод в цель-c не должен быть слишком сложным для поиска.
Интересный факт: в целях тестирования и чтобы найти подходящие размеры для моей фальшивой кнопки, я установил синий цвет ее фона ... И он отображается за кнопкой "Назад"! Во всяком случае, он все еще ловит любое прикосновение, нацеленное на оригинальную кнопку.
источник
Этот метод позволяет изменить текст кнопки «назад», не затрагивая заголовок любого из контроллеров представления или не видя изменения текста кнопки «Назад» во время анимации.
Добавьте это к методу init в вызывающем контроллере представления:
источник
Самый простой способ
Вы можете использовать методы делегата UINavigationController. Метод
willShowViewController
вызывается, когда нажата кнопка «Назад» вашего ВК.источник
Вот мое решение Swift. В вашем подклассе UIViewController переопределите метод navigationShouldPopOnBackButton.
источник
Нашел решение, которое сохраняет стиль кнопки назад. Добавьте следующий метод к вашему контроллеру представления.
Теперь предоставьте необходимую функциональность в следующем методе:
Все, что он делает - это закрывает кнопку назад прозрачной кнопкой;)
источник
========================================
Опираясь на предыдущие ответы с UIAlert в Swift5 в асинхронном режиме
На вашем контроллере
источник
Я не верю, что это возможно, легко. Единственный способ обойти это - создать собственное изображение стрелки назад, чтобы разместить его там. Поначалу это меня расстраивало, но я понимаю, почему, из соображений последовательности, это было опущено.
Вы можете приблизиться (без стрелки), создав обычную кнопку и скрыв кнопку возврата по умолчанию:
источник
Там более простой способ, просто наследование метода делегата из
UINavigationBar
и переопределить вShouldPopItem
методе .источник
Решение onegray небезопасно. Согласно официальным документам Apple, https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html мы не должны этого делать.
«Если имя метода, объявленного в категории, совпадает с именем метода в исходном классе или методом в другой категории в том же классе (или даже в суперклассе), поведение не определено относительно того, какая реализация метода используется во время выполнения. Это менее вероятно, будет проблемой, если вы используете категории со своими собственными классами, но могут вызвать проблемы при использовании категорий для добавления методов в стандартные классы Cocoa или Cocoa Touch. "
источник
Используя Swift:
источник
Вот версия Swon 3 ответа @oneway для отлавливания события кнопки возврата на панели навигации до того, как оно будет запущено. Как
UINavigationBarDelegate
нельзя использоватьUIViewController
, вам нужно создать делегат, который будет запускаться приnavigationBar
shouldPop
вызове.А затем в вашем контроллере представления добавьте функцию делегата:
Я понял, что мы часто хотим добавить контроллер предупреждений для пользователей, чтобы решить, хотят ли они вернуться. Если да, то вы всегда можете
return false
вnavigationShouldPopOnBackButton()
функции и закрыть контроллер представления, делая что - то вроде этого:источник
Value of type 'UIViewController' has no member 'navigationShouldPopOnBackButton'
когда я пытаюсь скомпилировать ваш код, для строкиif vc.responds(to: #selector(v...
такжеself.topViewController
возвращается необязательный параметр, и для этого также есть предупреждение.let vc = self.topViewController as! MyViewController
и пока он работает нормально. Если вы считаете, что это правильное изменение, вы можете отредактировать код. Также, если вы чувствуете, что этого не следует делать, я буду рад узнать, почему. Спасибо за этот код. Вы, вероятно, должны написать сообщение в блоге об этом, так как этот ответ похоронен согласно голосам.MyViewController
возможно, не соответствуетеBackButtonDelegate
. Вместо того, чтобы принудительно разворачивать, вы должны сделать,guard let vc = self.topViewController as? MyViewController else { return true }
чтобы избежать возможного сбоя.guard let vc = self.topViewController as? MyViewController else { self.popViewController(animated: true) return true }
убедиться, что экран перемещается на нужную страницу в случае, если его нельзя правильно воспроизвести. Теперь я понимаю, чтоnavigationBar
функция вызывается во всех VC, а не только в viewcontroller, где этот код существует. Может быть, будет полезно обновить код и в вашем ответе? Спасибо.Версия Swift 4 для iOS 11.3:
Это основано на ответе от kgaidis от https://stackoverflow.com/a/34343418/4316579
Я не уверен, когда расширение перестало работать, но на момент написания этой статьи (Swift 4) кажется, что расширение больше не будет выполняться, пока вы не объявите соответствие UINavigationBarDelegate, как описано ниже.
Надеюсь, что это помогает людям, которые задаются вопросом, почему их расширение больше не работает.
источник
Используя переменные target и action, которые вы в настоящий момент оставляете «nil», вы сможете связать свои диалоги сохранения так, чтобы они вызывались, когда кнопка «выбрана». Остерегайтесь, это может быть вызвано в странные моменты.
Я согласен в основном с Amagrammer, но не думаю, что было бы так сложно сделать кнопку со стрелкой на заказ. Я бы просто переименовал кнопку «Назад», сделал снимок экрана, сделал фотошоп нужного размера кнопки, и это было изображение поверх вашей кнопки.
источник
Вы можете попытаться получить доступ к элементу правой кнопки NavigationBars и установить его свойство селектора ... вот ссылка на ссылку UIBarButtonItem , еще одна вещь, если эта работа, которая будет работать, - это установить правый элемент кнопки панели навигации на пользовательский UIBarButtonItem, который вы создать и установить его селектор ... надеюсь, это поможет
источник
Для формы, которая требует пользовательского ввода, подобного этой, я бы рекомендовал вызывать ее как «модальную» вместо части вашего стека навигации. Таким образом, они должны позаботиться о бизнесе в форме, а затем вы можете проверить ее и отклонить с помощью пользовательской кнопки. Вы даже можете создать навигационную панель, которая будет выглядеть так же, как и все остальное ваше приложение, но даст вам больше контроля.
источник
Чтобы перехватить кнопку «Назад», просто закройте ее прозрачным UIControl и перехватите прикосновения.
источник
По крайней мере, в Xcode 5 есть простое и довольно хорошее (не идеальное) решение. В IB перетащите элемент панели кнопок с панели «Утилиты» и поместите его в левую часть панели навигации, где будет кнопка «Назад». Установите метку «Назад». У вас будет функциональная кнопка, которую вы можете привязать к своему IBAction и закрыть свой viewController. Я делаю некоторую работу, а затем запускаю сеанс расслабления, и он работает отлично.
Что не является идеальным, так это то, что эта кнопка не получает стрелку <и не переносит предыдущий заголовок VC, но я думаю, что этим можно управлять. Для моих целей я установил новую кнопку «Назад» как кнопку «Готово», поэтому ее назначение понятно.
Вы также получите две кнопки «Назад» в навигаторе IB, но это достаточно просто обозначить для ясности.
источник
стриж
источник
Этот подход работал для меня (но кнопка «Назад» не будет иметь знак «<»):
источник
Быстрая версия ответа @ onegray
Теперь в любом контроллере просто соответствуют
RequestsNavigationPopVerification
и это поведение принимается по умолчанию.источник
использование
isMovingFromParentViewController
источник
viewDidDisappear
. Таким образом, он будет срабатывать только после того, как вид окончательно исчезнет.Ответ от @William, тем не менее, правильный, если пользователь запускает жест пролистывания назад,
viewWillDisappear
метод вызывается и дажеself
не будет находиться в стеке навигации (то естьself.navigationController.viewControllers
не будет содержатьself
), даже если пролистывание не завершен, и контроллер представления фактически не вытолкнут. Таким образом, решение будет:Отключите жест смахивания назад
viewDidAppear
и разрешите использование кнопки «Назад» только с помощью:Или просто используйте
viewDidDisappear
вместо этого следующее:источник
Решение, которое я нашел до сих пор, не очень хорошее, но оно работает для меня. Принимая этот ответ , я также проверяю, высовываю ли я программно или нет:
Вы должны добавить это свойство к своему контроллеру и установить его в YES перед программным выводом:
источник
Найден новый способ сделать это:
Objective-C
стриж
источник