33

Background:

I have a custom container controller, which just like UITabBarController, but with switch animation. And I use auto layout to achieve.
Because switch between child controllers is dynamic, the proper constraints are added to child view controller when its's view is added into container's view, not pre-setup in IB. (The constraints are added to the superview of course)

http://d.pr/i/q6NF Container Controller Nib Setup

PS: The detail of constraints
H:|[Child](Change the constraint's constant to animation from left/right to right/left)
H:[Child(==Super)]
V:|[Child]|

Where is the Problem:

One of the child controller is a navigation controller, things go wrong when the navigation controller present a modal view controller (using presentViewController:animated:completion:), and dismiss it(usingdismissViewControllerAnimated:completion:), after present/ dismiss the frame of navigation controller become (x, y, 0, 0), It seems like the auto layout becomes invalid, maybe the constraints been removed.

http://d.pr/i/VmvL The Present/ Dismiss Process

Research

I haven't use code to verify what happen to these constraints yet, but with Spark Inspector I see the views presentation change during the present/ dismiss process. When My navigation controller present a modal view controller, iOS just swap the whole navigation controller's view to the modal view controller's view. And when navigation controller's view come back, the auto layout doesn't work anymore.

Possible Solution

One of the solution I came up with is let my container controller present modal controller.

Or I just change my container controller to no auto layout.

The fact is ever since I start using auto layout, the problems this technique causes just dominate the benefits. Besides this problem, Every time the interface orientation changes, views inside my container controller just can't auto layout right, it seems subviews always use the frame of superview before orientation change. I double check the constraints I setup, there is no conflicts and no ambiguity.

My guess is that my custom container controller isn't compatible with presenting modal view controller and interface orientation change in Auto Layout system, even with constraints setup.

Xcode Environment

Xcode 5 beta, iOS 7SDK, target iOS6.1 Maybe Something not right with the SDK environment?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Michael Hui
  • 343
  • 1
  • 3
  • 6

6 Answers6

37

I had a similar problem. I was setting translatesAutoresizingMaskIntoConstraints = NO; on my root UIView. It appears the "outermost" UIView - the superview at the root of your hierarchy must use the default translatesAutoresizingMaskIntoConstraints = YES. Once I've removed this, everything worked as expected.

Community
  • 1
  • 1
Palimondo
  • 7,281
  • 4
  • 39
  • 58
  • 3
    I am having similar problem, when I dismiss viewcontroller, tableView slides down 64 pixels. I tried your trick by adding self.view.translatesAutoresizingMaskIntoConstraints = YES (also tried with NO), but still not working. Nothing changed in output. Still problem persists. Do you have any further suggestion? – Nitesh Borad Jul 28 '14 at 14:23
  • @NiteshBorad The root cause of my issue was `translatesAutoresizingMaskIntoConstraints = YES` on the root view (one that is the direct child of `UIWindow`. It's hard to guess where your `self.view` is in the hierarchy. – Palimondo Jul 28 '14 at 15:50
  • Hi @Palimondo , or other viewers. i posted a related question with a sample project with the issue here: http://stackoverflow.com/questions/40428075/segue-from-a-slpagingviewswift-vc-and-dismiss-the-destination-vc-to-return i can't find how to implemented the solutions provided here in my context (SLPagingView). i would appreciate it a lot if someone can take a look and help, Thanks! – Eyal Ben Yehuda Nov 08 '16 at 16:17
12

It is probably caused by ambiguous constraints. I recommend pause a running application and type a following command to console:

po [[UIWindow keyWindow] _autolayoutTrace] 
Tomáš Linhart
  • 13,509
  • 5
  • 51
  • 54
7

If you use auto layout between the UIWindow and your root view (to set the root view to fill the entire UIWindow) these constraints will get blown away by a full screen presentation of another view controller.

What happens, is the entire hierarchy of the full-screen presentation replaces everything below UIWindow - your original view is removed (blowing away the constraints) and the new view hierarchy substituted. Then when your review is replaced, these constraints are lost. You would need to recreate them somewhere like viewWillAppear: or just ensure your root view has self.view.translatesAutoresizingMaskIntoConstraints = NO;

Rob Glassey
  • 2,237
  • 20
  • 21
  • @Rob Glassey I have a tabbar controller from where i present a modal view controller when the in-call status bar is shown. The tabbar controller is created in code , and i have not set any constraints. But, after the modal view controller is presented, and dismissed, the tab bar moves up by 20 px. I used self.view.translatesAutoresizingMaskIntoConstraints = NO for tabbarcontrollers root view. Then it works fine. Am not sure why. Can you explain. – user694688 Apr 25 '16 at 07:42
5

I have also the same problem and when i tried this navigation controller it was working fine but not with present viewcontroller. Use this below view controller method along with translatesAutoresizingMaskIntoConstraints to solve this problem.

-(void) viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    self.view.translatesAutoresizingMaskIntoConstraints = NO;
}

Please let me now it you have any concern about it. Thanks

chandan
  • 2,453
  • 23
  • 31
0

I had a similar problem with table view cells that I was laying out with autolayout. Upon returning from a modal view, the cells had an invalid layout. I could re-layout each cell after viewDidAppear, but it looked terrible. Thanks to @palimondo's suggestion I started sniffing around translatesAutoresizingMaskIntoConstraints. It turns out that I was setting the content view of my table view cell to translatesAutoresizingMaskIntoConstraints = NO when I shouldn't have been.

Phil Viso
  • 643
  • 7
  • 11
  • I was running into a similar problem, I would present a view controller modally, and when I returned from the view, I was getting incompatible layout errors in my table cells. It ended up being my constraint's that I had set in the table cells. I used "recommended constraints". After I blew them all away and set them up manually (in IB) , everything worked as expected. – AJ Venturella Mar 26 '15 at 12:19
0

I had the same problem, with a search bar container as the misplaced element (inside a UIViewController, inside a UITabBarController). None of the other solutions I've seen worked, but I eventually managed to work around it by re-adding the layout constraint in the viewWillAppear:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem: self.searchBar.superview
                                                      attribute: NSLayoutAttributeTop
                                                      relatedBy: NSLayoutRelationEqual
                                                         toItem: self.view
                                                      attribute: NSLayoutAttributeTop
                                                     multiplier: 1
                                                       constant: 0]];
Paul
  • 1