UINavigationController: Как отменить событие кнопки «Назад»? - PullRequest
16 голосов
/ 25 февраля 2011

В моем UIViewController у меня есть UINavigationController с кнопкой возврата по умолчанию.Когда пользователь нажимает кнопку «Назад», должно появиться предупреждающее сообщение: «Вы действительно хотите вернуться назад?».Я знаю, что невозможно поймать событие кнопки назад.Можно только использовать viewWillDisappear и установить флаг:

- (void)viewWillDisappear:(BOOL)animated {
    if (backBtnPressed) {
        UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Question" message:@"Do you really want to go back?" delegate:self cancelButtonTitle:@"No" otherButtonTitles: @"Yes", nil] autorelease];
        [alert show];   
    }
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    if (buttonIndex == 0) {
        // don't go back!
        // cancel the back button event
    }
    else if (buttonIndex == 1) {
        // go back
    }
}

Но с этим кодом у меня нет шансов!Я не могу остановить событие кнопки «Назад», не так ли?

Нужно ли мне писать свою кнопку возврата и устанавливать ее как leftBarButtonItem?Или есть кто-нибудь с отличной идеей?: -)

Спасибо за помощь!

Ответы [ 8 ]

53 голосов
/ 02 октября 2013

Мой ответ из другой ветки соответствует этому вопросу. Так что я репост это здесь:

Я реализовал расширение UIViewController-BackButtonHandler . Для этого не нужно создавать подклассы, просто поместите это в свой проект и переопределите navigationShouldPopOnBackButton метод в UIViewController class:

-(BOOL) navigationShouldPopOnBackButton {
    if(needsShowConfirmation) {
        // Show confirmation alert
        // ...
        return NO; // Ignore 'Back' button this time
    }
    return YES; // Process 'Back' button click and Pop view controller
}

Загрузить пример приложения .

13 голосов
/ 07 ноября 2011

Что вам нужно сделать, это использовать делегат панели навигации, а не контроллер навигации.

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item;    // called at end of animation of push or immediately if not animated
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;  // same as push methods
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
9 голосов
/ 25 февраля 2011

viewWillDisappear - это метод делегата для события, когда представление исчезнет - и разработчик ничего не может с этим поделать!Если бы вы могли, это был бы viewShouldDisappear метод делегата.

Так что, я полагаю, единственный способ, как вы предлагаете, использовать пользовательский leftBarButtonItem.

7 голосов
/ 03 сентября 2016

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

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

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;

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

К сожалению, остаются некоторые проблемы.

  • Жест смахивания назад не вызывает этот метод.
  • Хотя кажется необходимым, о сбоях сообщается, вызывая popViewControllerAnimated: в этом методе.
  • Кнопка «Назад» остается серой при отмене всплывающих окон.

Проведите назад жестом

Нам нужно перехватить жест, установив делегата, как это сделано в https://stackoverflow.com/a/23173035/2400328.

Если UINavigationController находится в подклассах, это будет:

self.interactivePopGestureRecognizer.delegate = self

и реализации:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

Будьте внимательны при изменении свойства делегата, поскольку оно изменяется после вызова инициализатора.

Не звонит popViewControllerAnimated:

Несмотря на то, что без документов, можно позвонить на popViewControllerAnimated:, как в https://stackoverflow.com/a/26084150/2400328.

Это включает вызов navigationBar:shouldPopItem: из UINavigationController (из подкласса).

Кнопка Назад

Хотя это может быть незначительной деталью (особенно если вы разработали свою собственную кнопку «Назад»), есть простое решение (написанное мной :) https://stackoverflow.com/a/29440633/2400328

Вам нужно только установить свойство YES и NO.

auto item = navigationBar.topItem;
item.hidesBackButton = YES;
item.hidesBackButton = NO;
2 голосов
/ 25 февраля 2011

Вы можете использовать пользовательскую кнопку с графикой, которая выглядит точно так же, как кнопка «Назад», и создать пользовательское представление leftBarButtonItem как UIButton с этой графикой. Добавьте цель self к своей кнопке с помощью пользовательского селектора back: и отправьте туда свое предупреждение. Если пользователь нажимает «да», чтобы закрыть, отключите этот контроллер представления, если нет - ничего не делайте. Хитрость здесь в том, что кнопка выглядит точно так же, как кнопка назад на панели навигации.

1 голос
/ 11 ноября 2016

Если вы ищете способ сделать это в Swift на iOS 10, вы можете создать собственное UINavigationController, а затем расширение UINavigationBarDelegate:

class MyNavigationController : UINavigationController {

}
extension MyNavigationController : UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        return false
    }
}
1 голос
/ 25 февраля 2011

Лучше, если вы сделаете свою собственную кнопку возврата и сделаете ее левой кнопкой навигационного контроллера.Это определенно может помочь вам выполнить любое действие

0 голосов
/ 05 августа 2013

Метод

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;

делает то, что вы хотите.К сожалению, мы не должны делегировать UINavigationBar нашим собственным объектам: (

Документация Apple заявляет:

... Кроме того, объект контроллера навигацииавтоматически назначает себя в качестве делегата своего объекта UINavigationBar и не позволяет другим объектам изменять это отношение. ...

One / The? способ сделать то, что вы хотите, это вставить собственную кнопку возвратаВ этом методе вы проводите тесты и вызываете

[self.navigationController popViewControllerAnimated:true];

, если пользователю разрешено вернуться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...