1

I am using a UINavigationController as a rootViewController and having some navigation hierarchy issues. I am presenting a viewController modally from a show segue state, but when I dismiss the modal it returns the app back to the viewDidAppear navigationController state - which is the apps launch state. I think it is because even though I am calling the presentViewController function from the 2nd view in the show navigation stack, the modal is being handled by the parent rootViewController, so when the modal is dismissed it returns to the viewDidAppear state of the UINavigationController. I would like the modal to be dismissed and return to the viewcontroller that presented the modal (the 2nd screen in the show segue stack). Thanks for the help in advance!

// rootViewController

class MainNavigationController: UINavigationController {

  override func viewDidLoad() {
    super.viewDidLoad()

    let vc1 = TravelersFeedVC()
    let vc2 = ProfileVC()

    if isLoggedIn() {
        // assume user is logged in
        let homeController = HomeController()
        homeController.firstViewController = vc1
        homeController.secondViewController = vc2

        viewControllers = [homeController]

    } else {
        perform(#selector(showLoginController), with: nil, afterDelay: 0.01)
    }

  }

  fileprivate func isLoggedIn() ->  Bool {
    return UserDefaults.standard.isLoggedIn()
  }

  func showLoginController() {
    let loginController = LoginController()
    present(loginController, animated: true, completion: {
        // perhaps do something here later
    })

  }

}

// HomeController

class HomeController: UIViewController, FBSDKLoginButtonDelegate {

    // child view controllers to put inside content view
    var firstViewController: TravelersFeedVC?
    var secondViewController: ProfileVC?

    private var activeViewController: UIViewController? {
        didSet {
            removeInactiveViewController(inactiveViewController: oldValue)
            updateActiveViewController()
        }
    }

    private func removeInactiveViewController(inactiveViewController: UIViewController?) {
        if let inActiveVC = inactiveViewController {
            // call before removing child view controller's view from hierarchy
            inActiveVC.willMove(toParentViewController: nil)

            inActiveVC.view.removeFromSuperview()

            // call after removing child view controller's view from hierarchy
            inActiveVC.removeFromParentViewController()
        }
    }

    private func updateActiveViewController() {
        if let activeVC = activeViewController {
            // call before adding child view controller's view as subview
            addChildViewController(activeVC)

            activeVC.view.frame = contentView.bounds
            contentView.addSubview(activeVC.view)

            // call before adding child view controller's view as subview
            activeVC.didMove(toParentViewController: self)
        }
    }

    // UI elements
    lazy var contentView: UIView = {
        let tv = UIView()
        tv.backgroundColor = UIColor.purple
        tv.translatesAutoresizingMaskIntoConstraints = false
        tv.layer.masksToBounds = true
        return tv
    }()


    var segmentedController: UISegmentedControl!

    override func viewDidLoad() {
        super.viewDidLoad()

        activeViewController = firstViewController

//        checkIfUserIsLoggedIn()

        view.addSubview(contentView)

        setupProfileScreen()

        //        navigationItem.title = "Home"
        let items = ["Travelers", "Me"]
        segmentedController = UISegmentedControl(items: items)
        navigationItem.titleView = segmentedController

        segmentedController.tintColor = UIColor.black
        segmentedController.selectedSegmentIndex = 0

        // Add function to handle Value Changed events
        segmentedController.addTarget(self, action: #selector(HomeController.segmentedValueChanged(_:)), for: .valueChanged)    
    }


    // reference to collectionViewController
    var travelersFeedVC: TravelersFeedVC!

    func segmentedValueChanged(_ sender:UISegmentedControl!)
    {
        switch segmentedController.selectedSegmentIndex {
        case 0:
            activeViewController = firstViewController

        case 1:
            activeViewController = secondViewController

        default: // Do nothing
            break
        }
    }

// tableviewcontroller where button is tapped to present viewController - this tableViewController is the 2nd in a show navigation stack

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "+ place", style: .plain, target: self, action: #selector(handleSearchPlaces))

    } 

    func handleSearchPlaces() {
        let _: UIViewController! = self.presentingViewController as? PlacesTableVC
        let vc = SearchPlacesController()
        let navController = UINavigationController(rootViewController: vc)
        present(navController, animated: true, completion: nil)
    }

// modal viewController to be dismissed and return user to tableview * not rootViewController app load state

class SearchPlacesController: UITableViewController { 
    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "back", style: .plain, target: self, action: #selector(returnToPlacesTableVC))

    }

    func returnToPlacesTableVC(sender: AnyObject) {
        // save the presenting ViewController
        let presentingViewController: UIViewController! = self.presentingViewController as? PlacesTableVC

        self.dismiss(animated: true) {
        // I want to go back to PlacesTableVC - NOT RootViewController with selectedIndex 0
        presentingViewController?.dismiss(animated: true, completion: nil)

        }
    }
}
JP Silvashy
  • 46,977
  • 48
  • 149
  • 227
user3708224
  • 1,229
  • 4
  • 19
  • 37

0 Answers0