Uiviewcontrollerhierarchyinconsistency When Trying to Present a Modal View Controller

UIViewControllerHierarchyInconsistency when trying to present a modal view controller

This happened to me already twice in the newest Xcode release.
In both cases I needed to make changes to the UIViewController's XIB file (In you case it would be MapViewController.xib:

BEFORE:

Sample Image

  1. Move main View out of View Controller's children:
  2. Remove View Controller from the XIB (it is not necessary since File's Owner should be of its Class already):

AFTER:

Sample Image

UIViewControllerHierarchyInconsistency when presenting view controller

You shouldn't try to use root view controller of a window as a modal. If you want to implement this transition using a window, then use an empty UIViewController with a clear background as the rootViewController and then present your composeViewController as a modal.

You could accomplish what you're trying to do without using windows. For example on iOS 8, use UIModalPresentationOverFullScreen as modalPresentationStyle for your composeViewController and simply present it as a modal for your current controller. Again, you'd need a transparent container view to do that, but it's cleaner than introducing another window. On iOS 7 you'd need to use UIModalPresentationCustom (seems to be giving the same effect as UIModalPresentationOverFullScreen by default)

UIViewControllerHierarchyInconsistency

I had the same error arise when I wanted a settings scroll view to appear in a popover.

Here is my original code with comments about what I changed to resolve it:

SettingsViewController *settingsViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
settingsViewController = [storyboard instantiateViewControllerWithIdentifier:@"Settings"];

CGRect contentRect = CGRectMake(10, 10, 320, 700);

// This entire object got deleted in the fixed version
UIViewController *popoverContent = [[UIViewController alloc] init];
popoverContent.view = settingsViewController.view;
popoverContent.contentSizeForViewInPopover = contentRect.size;

// Instead of popoverContent I just put the settingsViewController in directly.
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];

[popoverController presentPopoverFromRect:[sender frame]
inView:(UIButton*)sender
permittedArrowDirections:UIPopoverArrowDirectionLeft
animated:YES];

The line popoverContent.view = settingsViewController.view is what was causing the crash (without it my popover was empty of course). From the point of view of the UIViewControllerHierarchyInconsistency error it makes sense that I shouldn't have been reassigning it and then adding it to another view controller.

In your case I'd guess something similar is happening in pushViewController or elsewhere in your code. Could that be the case at all?

UIViewControllerHierarchyInconsistency clear association

You shouldn't call viewWillAppear and viewDidAppear. Those are supposed to be methods where the framework calls you.

Instead of trying to give the reservationListController's view to a different controller, you should push reservationListController.

UIViewControllerHierarchyInconsistency in 64 bit iOS device

I am able to resolve this issue by changing the code. In the previous code, I was adding the view controller as child view controller and removed previous view controller from parent view. That code was working fine in non-64 bit device, but not on 64 bit device. So I just added view controller's view into subview of the container view and removed previous view controller from super view. Here is the modified code for reference:

if(_currentViewController == nil)
{
_currentViewController = viewController;
[self.containerView addSubview:viewController.view];
}
else if(_currentViewController != viewController)
{
[_currentViewController.view removeFromSuperview];
[self.containerView addSubview:viewController.view];
_currentViewController = viewController;
}

It works fine on all device.

UIViewControllerHierarchyInconsistency - A view can only be at most with one view controller at a time

The main thing to get the mail compose view controller to show is to present it using the currently-active UIViewController. You didn't share enough of your code for this to be clear to me, but if self is a UIViewController in that context, you'd need to do:

[self presentViewController:picker animated: YES completion:nil];

If self isn't a UIViewController, replace self in the code above with a variable referencing the current UIViewController.

Youtube video inside modal ViewController, strange crash 'UIViewControllerHierarchyInconsistency'

This is not an error on part of the UIWebView.

What happened was that Apple finally became strict as to the way in which it maintains the application's view hierarchy. Prior to iOS 5.x, developers were able to remove a view from one hierarchy and add it to another. The perfect example of this would be say, the application's main view hierarchy; when presenting a modal view controller, this modal view controller has its own view hierarchy which isn't part of the application's view hierarchy; therefore, if the modal view controller had a subview and within that view it had say a movie (which happens to be a view as well) and this movie were to be maximized, the movie's view would be removed from the modal view controller's hierarchy and added to the application's view hierarchy...

application                                              modal view controller
| |
| |
window view
| |
| |
|---------------- ------------------
| | | |
| | | |
subview 1 subview 2 subview 3 movie

As may be seen, the modal view controller's view hierarchy lies outside of the application's view hierarchy, this was not a problem prior to iOS 5.x because, when the modal view controller was presented and the movie was maximized, what Apple did was the following:

application                                              modal view controller
| |
| |
window view
| |
| |
|------------------------- ------------
| | | |
| | | |
movie subview 1 subview 2 subview 3

With the movie appearing above all the other views. This no longer is the case in iOS 5.x+, it is an error to do that and you will be presented with the error with which you were, previously, greeted.

In order to work-around this issue, you need to make the modal view controller's view into the application's view hierarchy by not presenting the view controller as a modal view controller and, then, adding the view controller's view to the application's hierarchy as follows:

                                                          application
|
|
modal view controller window
| |
| |
---------------------------------------------------------------
| | |
| | |
view subview 1 subview 2
|
|
-------------------
| |
| |
subview 3 movie

From this point forward, everyone needs to really think, from the very beginning, how to properly structure view hierarchies and how they will interact with one another, as well as future scalability within those large projects.

This issue was well-documented by Apple during their 2011 WWDC. It is discussed within Session 102.

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

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.

Presenting a View Controller when the Interface Orientation is Upside Down

I guess that MFMailComposeViewController doesn't support upside down interface orientation that's why it could be interpreted as bug. But Apple recommends do not use upside down interface orientation for iPhone apps. The main reason of it could be explained by such example:

  1. User opens application and rotate iPhone to upside down orientation.
  2. At this moment somebody calls him by phone.
  3. User tries to answer the calls and forgets to rotate phone to default portrait orientation.
  4. As result iPhone's microphone is near user's ear and speaker near mouth.

It isn't user-friendly experience.

I would have thought on your site to use upside down orientation or not.

However if using of upside down interface orientation is required condition then you make such trick:

Create category to MFMailComposeViewController and override method supportedInterfaceOrientations to allow support of necessary orientations and import it to class were MFMailComposeViewController is created:

// MFMailComposeViewController+Orientation.h file
#import <MessageUI/MessageUI.h>

@interface MFMailComposeViewController (Orientation)

@end

// MFMailComposeViewController+Orientation.m file
#import "MFMailComposeViewController+Orientation.h"

@implementation MFMailComposeViewController (Orientation)

- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

@end

Notice: I am not sure that this trick would be passed throw Apple application approving center cause of overriding existed methods in category.



Related Topics



Leave a reply



Submit