0

I am relatively new to Swift Trying to use peek and pop previewActionItems "edit" to open the SpeciesDetailViewController in edit mode. Had an issue trying to get the segue to present the SpeciesDetailViewController and was getting an error message "Warning: Attempt to present SpeciesDetailViewController whose view is not in the window hierarchy". I implemented Jacob Davis' solution on found here.

This fixed the window hierarchy error, however when the SpeciesDetailViewController controller is called, both the navigation controller and tabBarController are NOT displaying.

enter image description here

While I believe this is caused by the SpeciesDetailViewController being called as top viewController, I am at a loss on how to fix this.

Can you please help me display both the navigation controller and tabBarController?

Below are my current codes:

Main View Controller

func showDetailsViewController() {

    let topVC = topMostController()
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "SpeciesDetailViewController") as! SpeciesDetailViewController
    topVC.present(vc, animated: true, completion: nil)

}

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }

    return topController
}
David Sanford
  • 735
  • 12
  • 26

1 Answers1

0

For UITabBarController and UINavigationController you need a different implementation.

Here is code I'm using to get topMostViewController:

protocol TopUIViewController {
    func topUIViewController() -> UIViewController?
}

extension UIWindow : TopUIViewController {
    func topUIViewController() -> UIViewController? {
        if let rootViewController = self.rootViewController {
            return self.recursiveTopUIViewController(from: rootViewController)
        }

        return nil
    }

    private func recursiveTopUIViewController(from: UIViewController?) -> UIViewController? {
        if let topVC = from?.topUIViewController() { return recursiveTopUIViewController(from: topVC) ?? from }
        return from
    }
}

extension UIViewController : TopUIViewController {
    @objc open func topUIViewController() -> UIViewController? {
        return self.presentedViewController
    }
}

extension UINavigationController {
    override open func topUIViewController() -> UIViewController? {
        return self.visibleViewController
    }
}

extension UITabBarController {
    override open func topUIViewController() -> UIViewController? {
        return self.selectedViewController ?? presentedViewController
    }
}

Now you can use this to get topUIViewController from your application regardless of UIViewController stack you have, including UINavigationController, UITabBarViewController.

let topVC = UIApplication.shared.keyWindow!.rootViewController!.topUIViewController()
Grzegorz Krukowski
  • 18,081
  • 5
  • 50
  • 71
  • Thanks, Grzegorz. However, i must admit I am a bit lost on how to implement this. Can you give an example about displaying the NavigationBar? – David Sanford Nov 25 '17 at 21:24
  • I'm not entirely sure, maybe I misunderstood your problem - can you edit your question with the UIViewController hierarchy you have and where exactly you want to display new UIViewController? – Grzegorz Krukowski Nov 25 '17 at 21:37
  • Grzegorz, I changed it some, but as I have about 3000 lines in the Class, I am not sure what you would need to see. – David Sanford Nov 25 '17 at 21:51