13
votes

I have a UIPageViewController with a simple UIViewController inside of it.

If the the UIViewController has no subviews, its view resizes correctly when rotated. (Solid green background).

portraitlandscape

If the the UIViewController has a subview with a fixed frame, its view resizes correctly when rotated. (Solid green background with yellow square in corner).

portraitlandscape

If the the UIViewController has a subview with its auto layout constraints set to fill its superview, its view no longer resizes correctly when rotated. (Solid yellow background with the UIPageViewController's red background visible). The auto layout code I use is:

UIView *v = [[UIView alloc] init];
[v setTranslatesAutoresizingMaskIntoConstraints:NO];
[v setBackgroundColor:[UIColor yellowColor]];
[[self view] addSubview:v];

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(v);

NSArray *cs = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" options:0 metrics:nil views:viewsDictionary];
[[self view] addConstraints:cs];

cs = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" options:0 metrics:nil views:viewsDictionary];
[[self view] addConstraints:cs];

portraitlandscape

Why would the auto layout of a subview affect its superview? This only happens if it is contained within a UIPageViewController.

4

4 Answers

11
votes

I had this problem too and the previous answers didn't seem to help much. I needed to add constraints to the scrollview used with the PageViewController.

// Add Paging View Controller
self.addChildViewController(self.pageViewController)
self.pageViewController.didMoveToParentViewController(self)
self.containerView.addSubview(self.pageViewController.view)

// Add Constraints
var verticalConstraints:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:|[View]|", options: nil, metrics: nil, views: ["View":self.pageViewController.view])
var horizontalConstraints:Array = NSLayoutConstraint.constraintsWithVisualFormat("|[View]|", options: nil, metrics: nil, views: ["View":self.pageViewController.view])

self.pageViewController.view.setTranslatesAutoresizingMaskIntoConstraints(false)
self.containerView.addConstraints(verticalConstraints)
self.containerView.addConstraints(horizontalConstraints)

// Add Constraints for the Scrollview
//This line is a bit of a hack.  If Apple ever changes the structure of the UIPageViewController, this could break.
let scrollView = self.pageViewController.view.subviews.first! as UIView  
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|[View]|", options: nil, metrics: nil, views: ["View":scrollView])
horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("|[View]|", options: nil, metrics: nil, views: ["View":scrollView])
self.pageViewController.view.addConstraints(verticalConstraints)
self.pageViewController.view.addConstraints(horizontalConstraints)
7
votes

The page view controller's view is not the superview of the views that represent the pages. The page view controller's view has a view hierarchy consisting of a custom scroll view subclass, and that scroll view in turn has three generic view subclasses, one each for the views of contained view controllers at indices 0 through 2. Those serve as the superviews for your contained views. You would have to target your auto layout constraints to those views. But it's much easier to use the autoresizing masks and let them get converted to auto layout constraints.

0
votes

I figured it out:

I had called [[_pageViewController view] setTranslatesAutoresizingMaskIntoConstraints:NO]; in the container controller class and not explicitly set the auto layout constraints on its view (or views, as Bored Astronaut mentioned).

0
votes

@Bored Astronaut answer almost worked for me. The only thing I've did besides leaving autoresizing masks to convert to auto layout constraints is to set UIPageViewController's view frame, before adding it to parent view.

[self addChildViewController:pageViewController];
pageViewController.view.frame = self.view.frame;
[self.view addSubview:pageViewController.view];
[pageViewController didMoveToParentViewController:self];

Without setting the frame, the child view controllers will be displayed and positioned correctly in any orientation, but their subviews won't be properly layouted.