Eironeia
Eironeia

Reputation: 781

Detect if you are going to a new view controller or previous

I have a navigation view controller, imagine this situation:

My views contollers: vc1, vc2, vc3, vc4

My root navigation controller: nc

And the stack of view controllers is like this:

nc > vc1 > vc2 > vc3

Now I am in vc3. I want to know how detect if you are going to a previous view controller (vc2) or you are moving to a new one (v4).

Guess this should be checked on viewWillDisappear method.

I am trying to check it with:

self.isMovingFromParentViewController()

But it only returns true if the previous vc is the navigation root.

Any further information you need just let me know, thanks.

EDIT:

Pushing

self.navigationController?.pushViewController(imageViewController, animated: true)

Going to previous view controller:

I am not using dismiss, just swipping or pushing back button of the navigation.

(Swift 2.3)

Upvotes: 2

Views: 4172

Answers (3)

Eironeia
Eironeia

Reputation: 781

Well I have found this solution (same question) it's in objective-C but I translate it to Swift and I have made one more modifications. Since I don't do dismiss view controller then if you are not pushing view controller then you are going back.

    if let viewControllers = self.navigationController?.viewControllers {
        if viewControllers.count > 1 && viewControllers[viewControllers.count-2] == self {
            print("New view controller was pushed")
        }
        else {
            print("View controller was popped")
        }

    }

Thanks everyone!

Upvotes: 1

Lawliet
Lawliet

Reputation: 3499

UPDATED

Things are trickier if you want to know when the navigation bar pops an item, you need navigationBar:shouldPopItem:. Check this out for more information. If you want to do something before the pop, the best way I can think of is to extend the UINavigationController.

@objc public protocol NavigationBarDelegate {
    @objc optional func navigationBarShouldPop() -> Bool }

extension UINavigationController: UINavigationBarDelegate  {

    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        if viewControllers.count < (navigationBar.items?.count)! {
            // When it's being called twice
            return true
        }

        guard let vc = self.topViewController else { return true }
        var shouldPop = true

        if vc.responds(to: #selector(vc.navigationBarShouldPop)) {
            shouldPop = vc.navigationBarShouldPop()
        }

        if shouldPop {
            DispatchQueue.main.async {
                self.popViewController(animated: true)
            }
        } else {
            DispatchQueue.main.async {
                // To fix the problem of back button disabled
                let dimmed = navigationBar.subviews.flatMap {$0.alpha < 1 ? $0 : nil}
                UIView.animate(withDuration: 0.25, animations: {
                    dimmed.forEach { $0.alpha = 1 }
                })
            }
        }

        return false
    }
}

And then if you want to do anything before your view controller get popped

class VC3: UIViewController, NavigationBarDelegate {
    func navigationBarShouldPop() -> Bool {
        // Do whatever you want here
        return true
    }
}

ORIGINAL

Assuming that you are in vc3 and of course you use NavigationController now. There should be 3 scenarios:

(1) You want to go back to vc2

dismiss(animated: true, completion: nil)

(2) You want to navigate to a new view controller (vc4) and you use interface builder

let vc4 = VC4(nibName: "VC4View", bundle: nil)
navigationController?.pushViewController(vc4, animated: true)

(3) You want to pop to a view on stack but not the immediately previous one. E.g., vc1

// If the destination view controller is already on the stack, just pop to it
for item in (navigationController?.viewControllers)! {
    if item.isKind(of: VC1.self)  {
       _ = navigationController?.popToViewController(item, animated: true)
    }
}

Upvotes: 1

Sandeep Ahuja
Sandeep Ahuja

Reputation: 931

If ViewDidLoad called, then you are pushing a new ViewController, else ViewController is already in the navigation controller stack and you are going to previous ViewController.

Upvotes: 0

Related Questions