robben
robben

Reputation: 785

Navigation between three view controllers, where all three of them are in one tab bar view

I have a tab bar view. In that, one of three tabs is a contacts app. In that contacts app, there are three pages, one to display all the contacts, second to display one particular contact selected in the first VC, and third is to add a new contact. (Pretty much similar to the built-in iOS app) How can I create a fluent flow between these three pages. (Do not forget they should be inside one tabbar)

I've added all the required buttons.

I've embedded 3 navigation view controller (one to each of the 3 pages)

First page has 'add' button that should lead to third page. Second page has two buttons, one to go back to first and the other to go to third. Third has two buttons, one each to go the each of the other two pages.

I've created these buttons programmatically inside the navigation bar using this function -

    override func viewDidAppear(_ animated: Bool) {
            navigationItem.title = "Add New Contact"
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.plain, target: self, action: #selector(theTransition))
       }

    @objc func theTransition() {
        let second = self.storyboard?.instantiateViewController(withIdentifier: "OneNavID") as! OneNavigationViewController
        self.present(second, animated: true, completion: nil)
    }

(The above code is an example of going from page 3 to 1)

These buttons are working properly, but they show a new page which is out of the tab bar controller. I want them to stay inside the tab view. Kindly help! Do ask if you have any doubt in the question. I've tried best to explain it in simple and short words. I've looked on the internet a lot, but I couldn't find any instance where each of three view controllers have one navigation controller each (which I assume is needed since each of them has incoming and outgoing links to/from other pages).

Second Page -

override func viewDidAppear(_ animated: Bool) {
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: UIBarButtonItem.Style.plain, target: self, action: #selector(theTransition))
    }

    @objc func theTransition() {
        let second = self.storyboard?.instantiateViewController(withIdentifier: "ThreeNavID") as! ThreeNavigationViewController
        self.present(second, animated: true, completion: nil)
    }

Third Page -

override func viewDidAppear(_ animated: Bool) {
        navigationItem.title = "Add New Contact"
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.plain, target: self, action: #selector(theTransition))
    }

    @objc func theTransition() {
        let second = self.storyboard?.instantiateViewController(withIdentifier: "NavID") as! NavigationViewController
        self.present(second, animated: true, completion: nil)
    }

Upvotes: 1

Views: 70

Answers (1)

RajeshKumar R
RajeshKumar R

Reputation: 15748

Don't use 3 navigation controllers. Use one navigation controller like this

UITabBarController_____ Another View Controller1 
                  |  
                  |____ Another View Controller2
                  |  
                  |____ Contact - UINavigationController -- FirstPage

UINavigationController -- FirstPage --> SecondPage --> ThirdPage

Embed the first Page in the navigation controller and push second and third pages. Don't create a new instance for the first page. Use popViewController to go to the previous view controller.


You can pass data to the next view controller with pushViewController and use custom delegate or closure to send data to the previous view controller. Or create a variable in custom navigation controller class like this

class CustomNavigationController: UINavigationController {
    var name: String?
}

Then read and write data from other view controllers like this

class FirstPage: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print((self.navigationController as? CustomNavigationController)?.name)
        (self.navigationController as? CustomNavigationController)?.name = "FirstPage"
    }
    @objc func goToSecondPage() {
        if let secondPage = self.storyboard?.instantiateViewController(withIdentifier: "SecondPage") as? SecondPage {
            self.navigationController?.pushViewController(secondPage, animated: true)
        }
    }
    @objc func goToThirdPage() {
        if let thirdPage = self.storyboard?.instantiateViewController(withIdentifier: "ThirdPage") as? ThirdPage {
            self.navigationController?.pushViewController(thirdPage, animated: true)
        }
    }
}

class SecondPage: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print((self.navigationController as? CustomNavigationController)?.name)
        (self.navigationController as? CustomNavigationController)?.name = "SecondPage"
    }
    @objc func goToThirdPage() {
        if let thirdPage = self.storyboard?.instantiateViewController(withIdentifier: "ThirdPage") as? ThirdPage {
            self.navigationController?.pushViewController(thirdPage, animated: true)
        }
    }
    @objc func goToFirstPage() {
        self.navigationController?.popViewController(animated: true)
    }
}
class ThirdPage: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print((self.navigationController as? CustomNavigationController)?.name)
        (self.navigationController as? CustomNavigationController)?.name = "ThirdPage"
    }
    @objc func goToFirstPage() {
        self.navigationController?.popToRootViewController(animated: true)
    }
    @objc func goToSecondPage() {
        self.navigationController?.popViewController(animated: true)
    }
}

Upvotes: 1

Related Questions