web-dev-qa-db-ja.com

UIViewControllerがナビゲーションスタックからポップされるかどうかを確認しますか?

アクションを実行できるように、View Controllerがnavスタックからポップされようとしていることを知る必要があります。

-viewWillDisappearを使用することはできません。これは、何らかの理由でView Controllerが画面外に移動したときに呼び出されるためです(新しいView Controllerが一番上にプッシュされるなど)。

コントローラーがいつポップされるのかを具体的に知る必要があります。

事前に感謝します。

56
Jasarien

これには明示的なメッセージはないと思いますが、UINavigationControllerをサブクラス化してpopViewControllerAnimatedをオーバーライドできます(自分でこれを試したことはありませんが)。

あるいは、View Controllerへの他の参照がない場合、その-deallocに追加できますか?

11
Tom Elliott

提示されたVCでviewWillDisappearメソッドをオーバーライドし、オーバーライド内でisMovingFromParentViewControllerフラグを確認して、特定のロジックを実行します。私の場合、Navigation Controllerのツールバーを隠しています。それでも、提示されたVCは完璧ではないがプッシュされたことを理解する必要があります。

77
Jeff Marino

UIViewControllerのカスタムサブクラスで willMoveToParentViewController:viewWillDisappear:の代わりに)をオーバーライドしてみてください。

View ControllerがコンテナView Controllerに追加または削除される直前に呼び出されます。

- (void)willMoveToParentViewController:(UIViewController *)parent
{
    [super willMoveToParentViewController:parent];
    if (!parent) {
        // `self` is about to get popped.
    }
}
25
ma11hew28

幸い、viewWillDisappearメソッドが呼び出されるまでに、viewControllerは既にスタックから削除されているため、viewControllerがself.navigationController.viewControllers

Swift 4

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if let nav = self.navigationController {
        let isPopping = !nav.viewControllers.contains(self)
        if isPopping {
            // popping off nav
        } else {
            // on nav, not popping off (pushing past, being presented over, etc.)
        }
    } else {
        // not on nav at all
    }
}

オリジナルコード

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ((self.navigationController) && 
        (![self.navigationController.viewControllers containsObject:self])) {
        NSLog(@"I've been popped!");
    }
}
18
caoimghgin

これは私のために働いています。

- (void)viewDidDisappear:(BOOL)animated
{
    if (self.parentViewController == nil) {
        NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
        //release stuff here
    } else {
        NSLog(@"PersonViewController view just hidden");
    }
}
12
Ronald Nepsund

ここでキャッチできます。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    if (viewController == YourAboutToAppearController) {
            // do something
    }
}

これは、新しいビューが表示される直前に発生します。まだ誰も動いていない。私はいつもasinine NavigationControllerの前で魔法をかけます。タイトルとボタンのタイトルを設定し、そこで何でもできます。

8
dieselmcfadden

私は同じ問題を抱えています。 viewDisDisappearで試しましたが、関数getがありません:((おそらく、私のVCがすべてUITableViewControllerであるためかわかりません。)Alexの提案はうまく機能しますが、Navigation Controllerこの場合、navコントローラーのすべてのVCには、サブクラス化したナビゲーションコントローラーではなく、UIMoreNavigationControllerとしてnavigationControllerがあるため、VCが間もなく通知されることはありません。ポップ。
最後に、UINavigationControllerのカテゴリの問題を解決し、書き直します-(UIViewController *)popViewControllerAnimated:(BOOL)animated

- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
   NSLog(@"UINavigationController(Magic)");
   UIViewController *vc = self.topViewController;
   if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
      [vc performSelector:@selector(viewControllerWillBePopped)];
   }
   NSArray *vcs = self.viewControllers;
   UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
   [self popToViewController:vcc animated:YES];
   return vcc;}

それは私にとってうまくいく:D

3
hiepnd

私はこれを試しました:

- (void) viewWillDisappear:(BOOL)animated {
    // If we are disappearing because we were removed from navigation stack
    if (self.navigationController == nil) {
        // YOUR CODE HERE
    }

    [super viewWillDisappear:animated];
}

アイデアは、ポップ時にView ControllerのnavigationControllerがnilに設定されるということです。そのため、ビューが消え、さらにnavigationControllerがある場合、ポップされたと判断しました。 (他のシナリオでは機能しない場合があります)。

ドキュメントに記載されていないため、popWillDisappearがポップ時に呼び出されることを保証できません。ビューがトップビューで、トップビューの下にあるときに試してみました-そして、両方で機能しました。

頑張って、オーデッド。

2
Oded Ben Dov

UINavigationControllerをサブクラス化し、popViewControllerをオーバーライドします。

スイフト3

protocol CanPreventPopProtocol {
    func shouldBePopped() -> Bool
}

class MyNavigationController: UINavigationController {
    override func popViewController(animated: Bool) -> UIViewController? {
        let viewController = self.topViewController

        if let canPreventPop = viewController as? CanPreventPopProtocol {
            if !canPreventPop.shouldBePopped() {
                return nil
            }
        }
        return super.popViewController(animated: animated)
    }

    //important to prevent UI thread from freezing
    //
    //if popViewController is called by gesture recognizer and prevented by returning nil
    //UI will freeze after calling super.popViewController
    //so that, in order to solve the problem we should not return nil from popViewController
    //we interrupt the call made by gesture recognizer to popViewController through
    //returning false on gestureRecognizerShouldBegin
    //
    //tested on iOS 9.3.2 not others
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        let viewController = self.topViewController

        if let canPreventPop = viewController as? CanPreventPopProtocol {
            if !canPreventPop.shouldBePopped() {
                return false
            }
        }

        return true
    }

}
1

これを使用できます:

if(self.isMovingToParentViewController)
{
    NSLog(@"Pushed");
}
else
{
    NSLog(@"Popped");
}
1
itechnician

([self.navigationController.viewControllers indexOfObject:self] == NSNotFound){//このビューのポップが発生した場合、viewwilldisappearでこのチェックを行ってみてください。 }

0
ravoorinandan

UINavigationBarDelegateのnavigationBar:shouldPopItemプロトコルメソッドを使用できます。

0
François P.