web-dev-qa-db-ja.com

UINavigationController:戻るボタンイベントをキャンセルするにはどうすればよいですか?

私の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に設定する必要がありますか?それとも素晴らしいアイデアを持っている人はいますか? :-)

ご協力いただきありがとうございます!

17
Manni

viewWillDisappearは、ビューが消えるイベントのデリゲートメソッドであり、開発者がそれについてできることは何もありません。可能であれば、それはviewShouldDisappearデリゲートメソッドになります。

したがって、あなたが提案するように、カスタムleftBarButtonItemを使用するのが唯一の方法だと思います。

9
James Bedford

別のスレッドからの私の answer はこの質問に一致します。だから私はここにそれを再投稿します:

IViewController-BackButtonHandler 拡張機能を実装しました。何もサブクラス化する必要はありません。プロジェクトに入れて、navigationShouldPopOnBackButtonクラスのUIViewControllerメソッドをオーバーライドするだけです。

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

サンプルアプリをダウンロード

53
onegray

あなたがする必要があるのは、ナビゲーションコントローラーではなく、ナビゲーションバーのデリゲートを使用することです。

- (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;
13
Enzo Tran

これは、Appleは簡単ではないようで、これを機能させるために多くの努力が払われているように見える一般的な使用例の1つであると言わなければなりません。多分私はここでの調査結果。

多くの人が指摘しているように、以下の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:を呼び出さない

文書化されていませんが、 https://stackoverflow.com/a/26084150/2400328 のようにpopViewControllerAnimated:を呼び出すことは避けられます。

これには、(サブクラスから)UINavigationControllernavigationBar:shouldPopItem:を呼び出すことが含まれます。

戻るボタン

これは些細なことかもしれませんが(特に、独自の[戻る]ボタンを設計した場合)、簡単な解決策があります(私が書いたもの:) https://stackoverflow.com/a/29440633/2400328 ==

プロパティYESとNOを設定するだけで済みます。

auto item = navigationBar.topItem;
item.hidesBackButton = YES;
item.hidesBackButton = NO;
7
techniao

「戻る」ボタンとまったく同じように見えるグラフィックスでカスタムボタンを使用し、このグラフィックスでUIButtonとしてカスタムleftBarButtonItemビューを作成できます。カスタムback:セレクターを使用して、ターゲットselfをボタンに追加し、そこにアラートをポップします。ユーザーが「はい」を押して終了した場合は、このビューコントローラーを閉じます。そうでない場合は、何もしません。ここでの秘訣は、ナビゲーションバーの戻るボタンとまったく同じように見えるボタンです。

2
Nava Carmon

独自の戻るボタンを作成し、それをナビゲーションコントローラーの左ボタンにするとよいでしょう。それは間違いなくあなたが任意のアクションを実行するのに役立ちます

1
visakh7

IOS10のSwift)でこれを行う方法を探している場合は、カスタムUINavigationControllerを作成してからUINavigationBarDelegate拡張子を作成できます。

class MyNavigationController : UINavigationController {

}
extension MyNavigationController : UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        return false
    }
}
1
Max

メソッド

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

あなたがやりたいことをやっています。残念ながら、UINavigationBarを独自のオブジェクトに委任することは想定されていません:(

Appleドキュメント 状態:

...さらに、ナビゲーションコントローラーオブジェクトは、それ自体をUINavigationBarオブジェクトのデリゲートとして自動的に割り当て、他のオブジェクトがその関係を変更するのを防ぎます。 .。

One/The?あなたがしたいことをする方法はあなた自身の戻るボタンを入れることです。そのメソッドでは、テストを実行して呼び出します

[self.navigationController popViewControllerAnimated:true];

ユーザーが戻ることを許可されている場合。

0