Attempt to present UIViewController on UIViewController whose view is not in the window hierarchy

404,267

Solution 1

Where are you calling this method from? I had an issue where I was attempting to present a modal view controller within the viewDidLoad method. The solution for me was to move this call to the viewDidAppear: method.

My presumption is that the view controller's view is not in the window's view hierarchy at the point that it has been loaded (when the viewDidLoad message is sent), but it is in the window hierarchy after it has been presented (when the viewDidAppear: message is sent).


Caution

If you do make a call to presentViewController:animated:completion: in the viewDidAppear: you may run into an issue whereby the modal view controller is always being presented whenever the view controller's view appears (which makes sense!) and so the modal view controller being presented will never go away...

Maybe this isn't the best place to present the modal view controller, or perhaps some additional state needs to be kept which allows the presenting view controller to decide whether or not it should present the modal view controller immediately.

Solution 2

Another potential cause:

I had this issue when I was accidentally presenting the same view controller twice. (Once with performSegueWithIdentifer:sender: which was called when the button was pressed, and a second time with a segue connected directly to the button).

Effectively, two segues were firing at the same time, and I got the error: Attempt to present X on Y whose view is not in the window hierarchy!

Solution 3

viewWillLayoutSubviews and viewDidLayoutSubviews (iOS 5.0+) can be used for this purpose. They are called earlier than viewDidAppear.

Solution 4

For Display any subview to main view,Please use following code

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController presentViewController:composeViewController animated:YES completion:nil];

For Dismiss any subview from main view,Please use following code

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController dismissViewControllerAnimated:YES completion:nil];

Solution 5

I also encountered this problem when I tried to present a UIViewController in viewDidLoad. James Bedford's answer worked, but my app showed the background first for 1 or 2 seconds.

After some research, I've found a way to solve this using the addChildViewController.

- (void)viewDidLoad
{
    ...
    [self.view addSubview: navigationViewController.view];
    [self addChildViewController: navigationViewController];
    ...
}
Share:
404,267
Kyle Goslan
Author by

Kyle Goslan

Updated on August 05, 2022

Comments

  • Kyle Goslan
    Kyle Goslan almost 2 years

    Just started using Xcode 4.5 and I got this error in the console:

    Warning: Attempt to present < finishViewController: 0x1e56e0a0 > on < ViewController: 0x1ec3e000> whose view is not in the window hierarchy!

    The view is still being presented and everything in the app is working fine. Is this something new in iOS 6?

    This is the code I'm using to change between views:

    UIStoryboard *storyboard = self.storyboard;
    finishViewController *finished = 
    [storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
    
    [self presentViewController:finished animated:NO completion:NULL];
    
  • Kyle Goslan
    Kyle Goslan almost 12 years
    Thanks for the reply, I'll have a look at this and see if its whats causing it
  • Matt Mc
    Matt Mc almost 12 years
    @James you are correct, the view apparently is not in the hierarchy until after viewWillAppear has been resolved and once viewDidAppear has been called. If this were my question I would accept this answer ;)
  • Ali
    Ali over 11 years
    @james Thanks. Using the ViewDidAppear solved the problem for me too. Makes sense.
  • Marc Endtricht
    Marc Endtricht over 11 years
    I wish I could upvote this twice. I just had this problem and came to the thread to find that I had already upvoted the last time I saw this.
  • Vincent
    Vincent over 11 years
    Note that when you change the VC in the viewDidAppear, this causes the execution of a segue, with Animation. Causes a flash/display of the background.
  • Jonny
    Jonny over 11 years
    Still they are used also in other occasions so I think they might be called several times in a view's "lifetime".
  • BootMaker
    BootMaker about 11 years
    Yes the trick is the viewWillAppear:(BOOL)animated as it's correct. One more important thing you have to call the super in the method, as [super viewDidAppear:animated]; without this it's not working.
  • foFox
    foFox almost 11 years
    I think you are missing [navigationViewController didMoveToParentViewController:self]
  • tooluser
    tooluser almost 11 years
    It's also not what the methods are for - as the name suggests. viewDidAppear is correct. Reading up on the view lifecycle is a good idea.
  • TMilligan
    TMilligan over 10 years
    This is the best solution. In my case, presenting in viewDidAppear causes a split second showing of the view controller before the modal is loaded, which is unacceptable.
  • surfrider
    surfrider about 10 years
    Same problem as Vincent mentioned. When presenting in ViewWillAppear, i have flickering presenting view controller before presented is appears.
  • Cruinh
    Cruinh about 9 years
    While this might work now, there's no guarantee that Apple will change behavior and break this on you in the future. Then when you go back to look at your code to try and fix things again, you'll wonder why you were doing this seemingly unnecessary dispatch.
  • Dannie P
    Dannie P about 9 years
    Dispatch with 0 time has saved me quite a number of times already - sometimes things that just should logically work don't normally work without it. So just make comments for yourself and others on why you do unobvious things (not only such a dispatch) and you should be fine.
  • love2script12
    love2script12 about 9 years
    For those who only looked at the upvoted answer, if you call if from AppDelegate, make sure it is called after [self.window makeKeyAndVisible]; Got this from another answer on this same page, but didn't want anyone to miss it
  • samouray
    samouray about 9 years
    I had the same error, and your answer here helped me figure out what was going on, it was indeed this error, fixed it because of you sir, thank you, +1
  • Vlad
    Vlad almost 9 years
    I mean that video should be stopped/paused first.
  • MCB
    MCB almost 9 years
    I deleted the old segue and connected VC to VC. Is there a way to connect the button to the storyBoard to the VC because that way just keeps erroring for me?
  • uplearned.com
    uplearned.com over 8 years
    This answer worked the best for me when trying to display an alert. The alert wouldn't show when I put it into viewDidLoad and viewWillAppear.
  • igraczech
    igraczech over 8 years
    BTW to understand WHERE do I call this method from... it's the otherwise UI-less SDK library, that displays its own UI over your app in certain (undisclosed) case.
  • Omar N Shamali
    Omar N Shamali about 8 years
    actually this helped me, it led me after to this stackoverflow.com/questions/20746413/…
  • Logicsaurus Rex
    Logicsaurus Rex about 8 years
    I tried your code, along with foFox's suggestion, and when I go to remove it from it's parent, it won't go away. Lololol. Still stuck with no fix.
  • iamburak
    iamburak about 8 years
    I had same error, your answer solved my problem, thanks for your attention. Kind regards.
  • Eugene Braginets
    Eugene Braginets almost 8 years
    if you have storyboard you can use perform segue and main_queue dispatch_async(dispatch_get_main_queue()) { }
  • Michael Peterson
    Michael Peterson almost 8 years
    You are just hacking around the problem and not solving it.
  • user3000868
    user3000868 almost 8 years
    In case anyone else has this problem, I had a similar problem using NSNotifications to trigger a method to presentViewController. I saw this solution but didn't think it applied to me as my methods weren't being called in viewDidLoad but then realized I had the addObserver for each notification in viewWillLoad --> 'view is not in the window hierarchy' error. When I moved the 'addObserver' to viewDidAppear, the errors disappeared.
  • Anton Tropashko
    Anton Tropashko over 7 years
    You WILL crash and burn if anyone decides to embed you sdk in an app that has an extension. Pass a UIViewController to abuse into you sdk init method[s].
  • igraczech
    igraczech over 7 years
    You're true Anton. This code was written when Extensions did not exist and SDK is not used in any of those yet. I've added a guard clause to skip this edge-case.
  • azizj
    azizj over 7 years
    Worked for me also
  • Borzh
    Borzh about 7 years
    lol, accidentally I also was creating two vc's: from button and performSegue, thanks for the tip!!!
  • Pokemon
    Pokemon about 7 years
    Works in Swift3.1
  • Iyyappan Ravi
    Iyyappan Ravi about 7 years
    @sunkehappy above two lines to be used in before presentviewcontroller, but its crashed why?
  • Vaibhav Limbani
    Vaibhav Limbani about 7 years
    @James Bedford Thanks ,you've saved my lot of time .Thank you very much :-)
  • shahtaj khalid
    shahtaj khalid almost 7 years
    how? can you elaborate? i'm facing the same problem. this is my code let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "SplashController") as UIViewController self.window?.rootViewController = initialViewControlleripad self.window?.makeKeyAndVisible()
  • Jaydeep Vyas
    Jaydeep Vyas over 6 years
    @James Bedford how to present view controller immediatly after the image is selected from gallery, because at the time uiimagepicker return me the image my controller is not appear
  • Samo
    Samo about 6 years
    In my case I was calling present(viewController, animated: true, completion: nil) inside a loop.
  • rayepps
    rayepps about 6 years
    This seems like a far more common issue that the many answers that have out voted yours. Unfortunate, this was extremely helpful
  • Teo Sartori
    Teo Sartori over 5 years
    This answer should be turned into an Xcode warning.
  • Mr Heelis
    Mr Heelis about 5 years
    yes all well and good but what is the solution... i have a background worker thread going to a server and displaying storyboards left right and centre and the entire methodology is bogus.. it's awful.. what should be a breeze is utterly a joke because al I want to do int he background thread is : wait wait decide push screen to front and it's IMPOSSIBLE is IOS????
  • Petey
    Petey over 2 years
    This was my issue. Thanks!