65

My app has a multi-pane tutorial-style view that users swipe through to learn about the app. This is implemented very much as described in this tutorial. Having implemented it for both iOS 7 and 8, I'm comparing how they work, and finding issues with the latter — I'm running Xcode 6 GM here.

It seems that the UIPageViewController is rendering the views after the transition is complete. I overrode the delegate methods to see what was going on:

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
   NSLog(@"Frame size before: %@", NSStringFromCGRect([(UIViewController*)pendingViewControllers[0] view].frame));
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
   NSLog(@"Frame size after: %@", NSStringFromCGRect([(UIViewController*)previousViewControllers[0] view].frame));
}

And here's a sample output:

Frame size before: {{0, 0}, {600, 600}}
Frame size after: {{0, 0}, {320, 568}}

This manifests like so: swipe to the left to pull in the next view, and note a 32-pt white space at the bottom of the new view. Once the transition is complete, it jerks into its proper layout.

Is this a bug in iOS 8, perhaps? I'm all out of guesses at this point.

Aaron Vegh
  • 5,217
  • 7
  • 48
  • 75
  • I also follow the same tutorial to create a PageViewController with 2 PageContentViewController which contains a UITextView. Both are exactly the same look and view. In fact, they are instances of the same class. When I swipe left to advance to next view, the text always jump down a line because the contentSize is changed at the very last. You can see that from the debug output. https://gist.github.com/5amfung/7918ca8f78556873dfa5 – Sam Sep 14 '14 at 01:15
  • 1
    I have the same issue, still not solved. – kelin Jan 26 '15 at 14:34

5 Answers5

113

I figured out you need to base your constraints on the view and not the layout guide of your view controller. This will ensure your view controller respects the constraints you set prior to the transition in a PageViewController.

you can do this like so:

Constraints example

Remember to uncheck "Constrain to margins"

dmzza
  • 2,308
  • 1
  • 21
  • 33
Darryl Bayliss
  • 2,677
  • 2
  • 19
  • 28
  • 17
    Once you do this, you might also have to deselect "Constrain to margins". – dfickling Oct 14 '14 at 23:25
  • 2
    Thanks for the answer! Of course you need to deselect "Constrain to margins" as @dfickling said – Gabriel Goncalves Nov 06 '14 at 21:26
  • This assumes there is always a status bar present. If there is not, then you are left with an empty gap on top -- e.g., when rotated into landscape mode. One could create an outlet for the appropriate constraints and alter them as runtime based on the existence of the status bar. – wcochran Jul 10 '15 at 00:13
  • This is cool. It fixed the problem. BTW, iOS 9 does not have this issue. – Jingshao Chen Oct 25 '15 at 17:40
  • @wcochran You are correct. Also if you rotate on iPhone other than Plus (SE for example) the gap is even bigger as the navigation bar is smaller on landscape. Also I see this on iOS 9 and 10 as well – kacho Sep 09 '17 at 18:01
41

For anyone having this issue, for me it appeared to be that I was laying out views "relative to margin" (a new feature in iOS 8).

Instead of:

enter image description here

Use:

enter image description here

dfickling
  • 2,545
  • 2
  • 16
  • 13
2

I've been struggling with this for a few days.

I tried to implement it by instantiating the page ViewController from the storyboard. There was a definite resizing occurring. Checking the frame size in

  1. pageViewController:viewControllerAfterViewController
  2. pageViewController:willTransitionToViewControllers
  3. pageViewController:didFinishAnimating:previousViewControllers

The frame size would always change between the calls to 1 and 3. Sometimes before 2 and sometimes after.

If you're also using storyboards, I was able to resolve the issue by extracting the page UI elements into its own XIB file, setting the constraints in IB and then creating the pages with a call to initWithNibName.

Not a complete answer but it returned me to feeling productive. Hope it helps.

widano
  • 21
  • 1
  • 1
1

For me solution was to pin top of the tableView to superview: Editor -> Pin -> Top Space To SuperView (iOS8)

Eugene Braginets
  • 856
  • 6
  • 16
0

It is a bug in iOS 8 but I found a workaround:

Add an empty view on top of the statusbar in your Storyboard. The height of the view should be as much as the y-value of your object that is being moved.

Image of correct constraints

AmiiQo
  • 353
  • 1
  • 7
  • 17
  • Unfortunately that doesn't seem to be doing anything for me. I placed a 32-pt view at the top and set constraints against it. Same thing is happening... Can you add any detail that I may have overlooked? – Aaron Vegh Sep 17 '14 at 17:42
  • Same issue discussed here: http://stackoverflow.com/a/25947290/2061520 I found the simplest solution (assuming you can avoid autolayout) is to unflag "Use Auto Layout" in storyboard. – HungryArthur Sep 20 '14 at 09:27