Warning: Attempt to present * on * whose view is not in the window hierarchy – swift

I’m trying to present a ViewController IF there is any saved data in the datamodel. But i get the above error: “Warning: Attempt to present * on *whose view is not in the window hierarchy” when the following IF-Statement is true.

override func viewDidLoad() {
        super.viewDidLoad()
        loginButton.backgroundColor = UIColor.orangeColor()

        var request = NSFetchRequest(entityName: "UserData")
        request.returnsObjectsAsFaults = false

        var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
        var context:NSManagedObjectContext = appDel.managedObjectContext!

        var results:NSArray = context.executeFetchRequest(request, error: nil)!

        if(results.count <= 0){
            print("Inga resultat")
        } else {
            print("SWITCH VIEW PLOX")
            let internVC = self.storyboard?.instantiateViewControllerWithIdentifier("internVC") as internViewController
            self.presentViewController(internVC, animated: true, completion: nil)
        }
    }

Iv’e tried different solutions found using Google.

  • Xcode / iOS: How to determine whether code is running in DEBUG / RELEASE build?
  • iOS app from AdMob error = com.google.DummyAdapter?
  • How to send Extra parameters in payload via Amazon SNS Push Notification
  • Safari web view opening when logging to FB through iOS 9
  • 6 duplicate symbols for architecture i386
  • Achieve smooth video scrubbing with AVPlayer
  • Cheers.

    10 Solutions Collect From Internet About “Warning: Attempt to present * on * whose view is not in the window hierarchy – swift”

    At this point in your code the view controller’s view has only been created but not added to any view hierarchy. If you want to present from that view controller as soon as possible you should do it in viewDidAppear to be safest.

    In objective c:
    This solved my problem when presenting viewcontroller on top of mpmovieplayer

    - (UIViewController*) topMostController
    {
        UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
        while (topController.presentedViewController) {
            topController = topController.presentedViewController;
        }
    
        return topController;
    }
    

    Swift 3

    I had this keep coming up as a newbie and found that present loads modal views that can be dismissed but switching to root controller is best if you don’t need to show a modal.

    I was using this

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc  = storyboard?.instantiateViewController(withIdentifier: "MainAppStoryboard") as! TabbarController
    present(vc, animated: false, completion: nil)
    

    Using this instead with my tabController:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let view = storyboard.instantiateViewController(withIdentifier: "MainAppStoryboard") as UIViewController
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    //show window
    appDelegate.window?.rootViewController = view
    

    Just adjust to a view controller if you need to switch between multiple storyboard screens.

    for SWIFT

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

    You just need to perform a selector with a delay – (0 seconds works).

        override func viewDidLoad() {
            super.viewDidLoad()
            perform(#selector(presentExampleController), with: nil, afterDelay: 0)
        }
    
        func presentExampleController() {
            let exampleStoryboard = UIStoryboard(named: "example", bundle: nil)
            let exampleVC = storyboard.instantiateViewController(withIdentifier: "ExampleVC") as! ExampleVC
            present(exampleVC, animated: true) 
        }
    

    Swift 3.

    Call this function to get the topmost view controller, then have that view controller present.

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

    Usage:

    let topVC = topMostController()
    let vcToPresent = self.storyboard!.instantiateViewController(withIdentifier: "YourVCStoryboardID") as! YourViewController
    topVC.present(vcToPresent, animated: true, completion: nil)
    

    For swift 3.0 and above

    public static func getTopViewController() -> UIViewController?{
    if var topController = UIApplication.shared.keyWindow?.rootViewController
    {
      while (topController.presentedViewController != nil)
      {
        topController = topController.presentedViewController!
      }
      return topController
    }
    return nil}
    

    I have tried so many approches! the only useful thing is:

    if var topController = UIApplication.shared.keyWindow?.rootViewController
    {
      while (topController.presentedViewController != nil)
      {
        topController = topController.presentedViewController!
      }
    }
    
    let storyboard = UIStoryboard(name: "test", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "teststoryboard") as UIViewController
    UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)
    

    This seemed to work to make sure it’s the top most view.

    I was getting an error

    Warning: Attempt to present myapp.testController: 0x7fdd01703990 on myapp.testController: 0x7fdd01703690 whose view is not in the window hierarchy!

    Hope this helps others with swift 3

    Swift 4

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