UPDATE

根据Tim的回答,我在每个具有scrollview(或子类)的视图控制器中实现了以下内容,它是我的自定义容器的一部分:

- (void)didMoveToParentViewController:(UIViewController *)parent
{
    if (parent) {
        CGFloat top = parent.topLayoutGuide.length;
        CGFloat bottom = parent.bottomLayoutGuide.length;

        // this is the most important part here, because the first view controller added 
        // never had the layout issue, it was always the second. if we applied these
        // edge insets to the first view controller, then it would lay out incorrectly.
        // first detect if it's laid out correctly with the following condition, and if
        // not, manually make the adjustments since it seems like UIKit is failing to do so
        if (self.collectionView.contentInset.top != top) {
            UIEdgeInsets newInsets = UIEdgeInsetsMake(top, 0, bottom, 0);
            self.collectionView.contentInset = newInsets;
            self.collectionView.scrollIndicatorInsets = newInsets;
        }
    }

    [super didMoveToParentViewController:parent];
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我有一个名为SegmentedPageViewController的定制容器视图控制器.我把它设为UINavigationController's rootViewController.

SegmentedPageViewController的用途是允许设置为NavController标题视图的UISegmentedControl在不同的子视图控制器之间切换.

在此处输入图像描述

这些子视图控制器都包含scrollview、tableview或collection视图.

我们发现,第一个视图控制器加载良好,正确定位在导航栏下方.但是当我们换到一个新的

在此处输入图像描述

我们正在使用自动布局和界面生成器.我们已经想尽一切办法,但找不到一致的解决方案.

以下是主要代码块,用于设置第一个视图控制器,并在用户点击分段控件时切换到另一个视图控制器:

- (void)switchFromViewController:(UIViewController *)oldVC toViewController:(UIViewController *)newVC
{
    if (newVC == oldVC) return;

    // Check the newVC is non-nil otherwise expect a crash: NSInvalidArgumentException
    if (newVC) {

        // Set the new view controller frame (in this case to be the size of the available screen bounds)
        // Calulate any other frame animations here (e.g. for the oldVC)
        newVC.view.frame = self.view.bounds;

        // Check the oldVC is non-nil otherwise expect a crash: NSInvalidArgumentException
        if (oldVC) {
            // **** THIS RUNS WHEN A NEW VC IS SET ****
            // DIFFERENT FROM FIRST VC IN THAT WE TRANSITION INSTEAD OF JUST SETTING


            // Start both the view controller transitions
            [oldVC willMoveToParentViewController:nil];
            [self addChildViewController:newVC];

            // Swap the view controllers
            // No frame animations in this code but these would go in the animations block
            [self transitionFromViewController:oldVC
                              toViewController:newVC
                                      duration:0.25
                                       options:UIViewAnimationOptionLayoutSubviews
                                    animations:^{}
                                    completion:^(BOOL finished) {
                                        // Finish both the view controller transitions
                                        [oldVC removeFromParentViewController];
                                        [newVC didMoveToParentViewController:self];
                                        // Store a reference to the current controller
                                        self.currentViewController = newVC;
                                    }];
        } else {

            // **** THIS RUNS WHEN THE FIRST VC IS SET ****
            // JUST STANDARD VIEW CONTROLLER CONTAINMENT

            // Otherwise we are adding a view controller for the first time
            // Start the view controller transition
            [self addChildViewController:newVC];

            // Add the new view controller view to the view hierarchy
            [self.view addSubview:newVC.view];

            // End the view controller transition
            [newVC didMoveToParentViewController:self];

            // Store a reference to the current controller
            self.currentViewController = newVC;
        }
    }

}

推荐答案

根据子视图控制器的automaticallyAdjustsScrollViewInsets属性,自定义容器视图控制器需要根据已知的导航栏高度调整第二个视图控制器的contentInset.(您可能还对容器的topLayoutGuide属性感兴趣——确保它在视图切换期间和之后返回正确的值.)

UIKit在如何应用这种逻辑方面非常不一致(而且有缺陷);有时,您会看到它通过到达层次结构中的多个视图控制器来自动执行此调整,但通常在自定义容器切换后,您需要自己完成这项工作.

Objective-c相关问答推荐

Swift 3 - dynamic vs @objc

删除 UITableView 分隔线

CFURLCopyResourcePropertyForKey 失败,因为通过 URL 没有方案

使用 Objective-C 在 iOS 9 中将状态栏文本 colored颜色 更改为浅色

未找到 RKObjectMapping.h

Xcode 7 警告:目标文件是为比链接更新的 iOS 版本构建的

WKWebView 判断 JavaScript 返回值

目标覆盖 FRAMEWORK_SEARCH_PATHS 构建设置

将输入视图添加到文本字段 iOS 8 时出错

Unwind Segue 在 iOS 8 中不起作用

iOS 8 iPhone 上的 UIPopoverPresentationController

UITableView 在半透明的导航栏下

在 iOS 7 上,如果最终包含在选项卡栏控制器中,则使用工具栏推送控制器会留下不可用空间的间隙

在 Xcode 5 中运行代码覆盖时出现数十个“profiling:invalid arc tag”

iOS - UITableViewCell 中 UIButton 的延迟“Touch Down”事件

如何更改标签栏上的非活动图标/文本 colored颜色 ?

关闭一次后如何返回“允许推送通知”对话框?

如何编写 Objective-C 完成块

使用 UIViewControllerInteractiveTransitioning 委托协议实现自定义 UIViewController 交互式过渡的正确方法

为什么 UIScrollView 在 ios 6 和 ios 7 中从顶部留下空间