13

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).

portrait landscape

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).

portrait landscape

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];

portrait landscape

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

Senior
  • 2,259
  • 1
  • 20
  • 31

4 Answers4

11

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)
Barlow Tucker
  • 6,229
  • 3
  • 36
  • 42
7

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.

Bored Astronaut
  • 994
  • 5
  • 10
  • Using autoresizing masks fixes the issue, thanks. I'm still unsure why the contained UIViewController's view would be affected by its child view's auto layout constraints. – Senior Jul 18 '13 at 18:28
0

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).

Senior
  • 2,259
  • 1
  • 20
  • 31
  • 2
    Hey Senior - I'm having the exact same issue described in your question. Would you be able to provide a little sample code with this answer? I am doing everything with auto layout via the Visual Format Language (just like you), and when I rotate, my UIPageViewController does exactly what yours did. You said "and not explicitly set the auto layout constraints on its view" - if you could provide the code for that, it would help me immensely and provide a more complete answer. Thanks! – DiscDev Feb 22 '14 at 23:18
0

@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.

nsinvocation
  • 7,559
  • 3
  • 41
  • 46