topLayoutGuide in child view controller

前端 未结 11 1996
既然无缘
既然无缘 2020-12-07 11:29

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

However, the ch

相关标签:
11条回答
  • 2020-12-07 12:14

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

    0 讨论(0)
  • 2020-12-07 12:14

    This is an unfortunate behavior that appears to have been rectified in iOS 11 with the safe-area API revamp. That said, you will always get the correct value off the root view controller. For example, if you want the upper safe area height pre-iOS 11:

    Swift 4

    let root = UIApplication.shared.keyWindow!.rootViewController!
    let topLayoutGuideLength = root.topLayoutGuide.length
    
    0 讨论(0)
  • 2020-12-07 12:19

    The documentation says to use topLayoutGuide in viewDidLayoutSubviews if you are using a UIViewController subclass, or layoutSubviews if you are using a UIView subclass.

    If you use it in those methods you should get an appropriate non-zero value.

    Documentation link: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instp/UIViewController/topLayoutGuide

    0 讨论(0)
  • 2020-12-07 12:19

    This has been addressed in iOS 8.

    How to set topLayoutGuide position for child view controller

    Essentially, the container view controller should constrain the child view controller's (top|bottom|left|right)LayoutGuide as it would any other view. (In iOS 7, it was already fully constrained at a required priority, so this didn't work.)

    0 讨论(0)
  • Swifty implementation of @NachoSoto answer:

    extension UIViewController {
    
        func navigationBarTopLayoutGuide() -> UILayoutSupport {
            if let parentViewController = self.parentViewController {
                if !parentViewController.isKindOfClass(UINavigationController) {
                    return parentViewController.navigationBarTopLayoutGuide()
                }
            }
    
            return self.topLayoutGuide
        }
    
        func navigationBarBottomLayoutGuide() -> UILayoutSupport {
            if let parentViewController = self.parentViewController {
                if !parentViewController.isKindOfClass(UINavigationController) {
                    return parentViewController.navigationBarBottomLayoutGuide()
                }
            }
    
            return self.bottomLayoutGuide
        }
    }
    
    0 讨论(0)
提交回复
热议问题