相同的视图控制器显示不同

Identical View Controllers Displaying Differently

我有两个子视图控制器,据我所知它们是相同的,但是其中一个出现意外。

这两个子视图控制器称为 MenuLoggedInViewControllerMenuLoggedOutViewController。他们的容器视图控制器具有以下代码:

override func viewDidLoad() {
    super.viewDidLoad()

    // i comment out one of these two lines to produce the different results:
    self.masterView = MenuLoggedOutViewController(nibName: "MenuLoggedOutViewController", bundle: nil)
    // self.masterView = MenuLoggedInViewController(nibName: "MenuLoggedInViewController", bundle: nil)

    self.detailView = RootViewController(nibName: "RootViewController", bundle: nil)
    self.masterViewFrame = CGRectMake(0, 0, self.view.frame.width, 50)
    self.detailViewFrame = CGRectMake(0, 50, self.view.frame.width, self.view.frame.height - 50)
    self.addChildViewController(masterView!)
    self.addChildViewController(detailView!)
    self.view.addSubview(masterView!.view)
    self.view.addSubview(detailView!.view)

    masterView!.view.frame = masterViewFrame
    // masterView!.view.bounds = masterViewFrame // - i tried this and it made no difference
    detailView!.view.frame = detailViewFrame
}

MenuLoggedInViewControllerMenuLoggedOutViewController 在它们的 swift 文件中有几乎相同的模板代码:

override func viewDidLoad() {
    super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

除了更改背景颜色外,我没有触及 .xib 文件。在完成 .xib 文件的设置后,它们 似乎 都是一样的。如果可以的话,我不会靠近故事板,所以我对它不太熟悉。但是我花了很长时间仔细检查两个 .xib 文件的所有值,除了背景颜色之外,我可以检测到它们之间没有区别。

如您所见,黑色 MenuLoggedInViewController 紧贴下方的白色视图控制器。这是有意的。

灰色背景是包含视图控制器的颜色。如您所见,黑色 MenuLoggedOutViewController 只下降了这么远。

任何人都可以向我解释一下,尽管几乎相同并且使用几乎相同的代码调用,为什么 MenuLoggedOutViewController 无法正确显示?

需要注意的是,如果屏幕旋转到一边然后再回到纵向,MenuLoggedOutViewController 会自行纠正。然后 MenuLoggedOutViewController 看起来应该是这样(比如 MenuLoggedInViewController)。

很难说清楚到底发生了什么。如果您真的想要,我建议您使用 NSStringFromCGRect 并检查各种 frame 值,我想您会看到发生了什么。

但关键的概念问题是此代码正在调整 viewDidLoad 中的 frame 值,但此时 frame 值并不可靠。我建议:

  • 将子 frame 值的调整移动到 viewWillLayoutSubviews。在这一点上,主视图的 frame 是可靠的。

  • 如果使用自动布局,根本不要设置 frame 值,而是将这两个子视图的 setTranslatesAutoresizingMaskIntoConstraints 设置为 false 和然后添加约束(您可以在 viewDidLoad 中执行),其 VFL 实际上是:

    V:|[master(50)][detail]|
    H:|[master]|
    H:|[detail]|
    

作为最后一个不相关的细节,在调用 addChildViewController 时,添加完子视图后,不要忘记为每个子视图控制器调用 didMoveToParentViewController