popping a view controller in different tab

2019-07-15 06:27发布

问题:

UPDATE This code appears to do what I want, but I am curious if this is a bad tactic now.

func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
    print("pop view controller from tab bar")

    if tabBarController.selectedIndex == 2 {
        print("appdel detected index 2 tab")
        let navCont = viewController as! UINavigationController
        navCont.popToRootViewControllerAnimated(true)
    }
}

ORIGINAL QUESTION: I have some code that will delete data another tab refers to. I want to make sure that when this code executes in [Edit Record VC] that it will force tab to pop back to the root view, even though the code executes on its own tab:

[ ---------------TAB BAR CONTROLLER ------------------ ]
  TAB 0              TAB 1         TAB 2           TAB 3
     |                 |              |              |
     |                 |              |              |
  [NAV CONTR 0]  [NAV CONTR 1]  [NAV CONTR 2]  [NAV CONTR 3]
                       |              |        
                       |              |  
                   [Table VC]      [Map VC]
                       \              /
                        \            /
                         \          /
                       [View Record VC]
                               |
                               |
                       [Edit Record VC]

In the above drawing, when I delete a record in [Edit Record VC], I want to pop Nav Controller 1 and Nav Controller 2 to the very first VC. How can I do this? I have tried every way I can think of and the code just isn't working.

The reason I want to do this is because if NAV CONTR 2 navigates to [Edit Record VC] and deletes the record, [View Record VC] will still be referencing that record, causing it to point to a deleted object. When I try to open the NAV CONTR 2 tab after deletion, it'll cause a crash

回答1:

Multiple objects reacting to an event sounds like a job for NSNotification.

Make NAV CONTR 1 and NAV CONTR 2 instances of a navigation controller subclass that listens for a notification (resetToFirstController or something). Make posting that notification part of the delete logic.

When each controller receives the notification it pops to its root...or whichever "safe" controller you choose.



回答2:

I wanted to show Phillip Mills actual implementation that I did that worked like a charm.

First please refer to this post on NSNotification, (NotificationCenter issue on Swift 3), this is a very good reference on the syntax in swift3.

So in the controller that you want to have the ability to pop to the root controller of the navigation you will need to add the following function with print being optional, but useful so you see what is going on.

    // MARK: - Notifications
    func resetToTopView(notification: NSNotification){
        _ = navigationController?.popToViewController(self, animated: true)
        print("poppedViewController for TABNAMEHERE Successfully!")
    }

Next you need to register this function so it can be called by the Notification center. Simply in the viewDidLoad of the same controller add the following NotificationCenter code.

func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(self.resetToTopView(notification:)), name: k_resetToTopViewForYourTabNotification, object: nil)
}

The code above will give an error if you do not set the constant in your program for k_resetToTopViewForYourTabNotification. I usually create a file somewhere called globals where I put these constants.

To define it put something like this there.

let k_resetToTopViewForYourTabNotification = Notification.Name("resetToTopViewForYourTabNotification")

Then in the other tab or for that matter anywhere else in your code that you are, even a different tab, if you want to call the function to pop the view controllers back to the root, you simply call this command.

NotificationCenter.default.post(name: k_resetToTopViewForYourTabNotification, object: nil)

Really simple and nice :).



回答3:

First Case:When you want to select other tab index

guard let VCS = self.navigationController?.viewControllers else {return }
for controller in VCS {
    if controller.isKind(of: TabBarController.self) {
        let tabVC = controller as! TabBarController
        tabVC.selectedIndex = index . (Select any index for tab)
        self.navigationController?.popToRootViewController(animated: true)
    }
}

Second Case: When you want to access to RootViewController variables

guard let VCS = self.navigationController?.viewControllers else {return }
for controller in VCS {
    if controller.isKind(of: TabBarController.self) {
        let tabVC = controller as! TabBarController
        //    tabVC.selectedIndex = 0 . //no need of this line if you want to access same tab where you have started your navigation
        let VCs = tabVC.selectedViewController as! MyViewController
        VCs.variableName = true . //access your variable
        self.navigationController?.popToRootViewController(animated: true)
    }
}