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)
}
}
}