UPDATE 2
I\'ve been running and testing my app in the iOS Simulator using a 4-inch device. If I run using a 3.5-inch device the label doesn\'t jump.
Try unchecking these 2 options on your storyboard
This is definitely being caused by automaticallyAdjustsScrollViewInsets
, as other posters (including @djibouti33). However, this property is strange in two ways:
UINavigationController
. If you set it on a child controller that's managed by a UINavigationController
, it won't have any effect. 1These two caveats should explain the intermittent problems experienced by others in the thread.
TLDR: A workaround that I went with is adding a dummy view to the UIPageViewController
at index zero, to avoid the setting applying to the scrollView within the page controller, like this:
pageViewController.view.insertSubview(UIView(), atIndex: 0) // swift
[pageViewController.view insertSubview: [UIView new] atIndex: 0]; // obj-c
Better would be to set the contentInset
on the scroll view yourself, but unfortunately the UIPageViewController
doesn't expose the scroll view.
Try to select PageViewController in storyboard and uncheck "Under Bottom Bars" and "Under Opaque Bars" in Attributes Inspector.
I'm seeing the same issue as described by @Danny on iOS 9. I tried updating all my constraints to that they are not constrained to the margins, but it didn't fix the issue. I ended up having to adopt a hack similar to this one as follows;
In each view controller with such an outlet, add another property for the preferred top distance. The two outlets look like this (in Swift):
@IBOutlet weak var topGuideConstraint: NSLayoutConstraint!
var topDistance: CGFloat!
In viewDidLoad()
, set topDistance
to the value assigned to the constraint in the storyboard:
override func viewDidLoad() {
super.viewDidLoad()
topDistance = topGuideConstraint.constant
}
In viewWillLayoutSubviews()
, make sure the constraint has the proper value, adjusting for the height of the status bar when the topLayoutGuide.length
is zero, which seems to be the case during the transition, but not once it's complete:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
topGuideConstraint.constant = topDistance + (
topLayoutGuide.length == 0
? UIApplication.sharedApplication().statusBarFrame.size.height
: 0
)
}
Repeat for every content view controller displayed in the UIPageViewController. Adjust the offset as appropriate if you're also displaying a UINavigation bar.
This is an unfortunate hack, and I hate having to do it, but after many hours trying different things, I'm at least happy to have something that works so I can move on.
I had a similar problem but none of the solutions here worked. My problem was that whenever I would scroll to the next page, the content would jump down, ending in the correct position, but starting 20 pixels too high (clearly something to do with the status bar). My container VC was not a nav VC. After pulling my hair out for a while, the solution that ended up working for me was just to make sure that none of the constraints in my content VC were connected to the top layout guide. This may or may not be feasible in your case, but in mine it was, and it was the only thing that solved the content jump. Also very curiously, this problem only manifested when the transition style was set to scroll. Just changing it to page curl made the issue disappear. But I needed scroll. Hope this helps someone else.
My original answer solved the problem for the time being, but after a while the same problem came back to bite me.
Using the following viewController hierarchy:
-- UINavigationController
-- MyPageViewController
-- MyDetailViewController
Here's what I did to solve it:
In MyPageViewController.m
@interface MyPageViewController () <delegates>
@property (strong) MyDetailViewController *initialViewController;
@end
- (void)viewDidLoad
{
...
// set this once, because we're going to use it in viewWillLayoutSubviews,
// which gets called multiple times
self.initialViewController = [MyDetailViewController new];
}
// the problem seemed to stem from the fact that a pageViewController couldn't
// properly lay out it's child view controller initially if it contained a
// scroll view. by the time we're in layoutSubviews, pageViewController seems to
// have gotten it's bearings and everything is laid out just fine.
- (void)viewWillLayoutSubviews
{
[self setViewControllers:@[self.initialViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:false
completion:nil];
}