Search code examples
iosuiviewcontrollerios7autolayoutuipageviewcontroller

topLayoutGuide in child view controller


I have a UIPageViewController with translucent status bar and navigation bar. Its topLayoutGuide is 64 pixels, as expected.

However, the child view controllers of the UIPageViewController report a topLayoutGuide of 0 pixels, even if they're shown under the status bar and navigation bar.

Is this the expected behavior? If so, what's the best way to position a view of a child view controller under the real topLayoutGuide?

(short of using parentViewController.topLayoutGuide, which I'd consider a hack)


Solution

  • While this answer might be correct, I still found myself having to travel the containment tree up to find the right parent view controller and get what you describe as the "real topLayoutGuide". This way I can manually implement automaticallyAdjustsScrollViewInsets.

    This is how I'm doing it:

    In my table view controller (a subclass of UIViewController actually), I have this:

    - (void)viewWillLayoutSubviews {
        [super viewWillLayoutSubviews];
    
        _tableView.frame = self.view.bounds;
    
        const UIEdgeInsets insets = (self.automaticallyAdjustsScrollViewInsets) ? UIEdgeInsetsMake(self.ms_navigationBarTopLayoutGuide.length,
                                                                                                   0.0,
                                                                                                   self.ms_navigationBarBottomLayoutGuide.length,
                                                                                                   0.0) : UIEdgeInsetsZero;
        _tableView.contentInset = _tableView.scrollIndicatorInsets = insets;
    }
    

    Notice the category methods in UIViewController, this is how I implemented them:

    @implementation UIViewController (MSLayoutSupport)
    
    - (id<UILayoutSupport>)ms_navigationBarTopLayoutGuide {
        if (self.parentViewController &&
            ![self.parentViewController isKindOfClass:UINavigationController.class]) {
            return self.parentViewController.ms_navigationBarTopLayoutGuide;
        } else {
            return self.topLayoutGuide;
        }
    }
    
    - (id<UILayoutSupport>)ms_navigationBarBottomLayoutGuide {
        if (self.parentViewController &&
            ![self.parentViewController isKindOfClass:UINavigationController.class]) {
            return self.parentViewController.ms_navigationBarBottomLayoutGuide;
        } else {
            return self.bottomLayoutGuide;
        }
    }
    
    @end
    

    Hope this helps :)