topLayoutGuide在viewWillAppear之后应用

时间:2017-05-14 11:53:26

标签: ios swift uiviewcontroller autolayout

我遇到的问题是topLayoutGuide.length(来自XIB)UIViewControllerviewWillAppear之后设置,我不知道如何挂钩{{1}的更改最初设置表视图的contentOffset。

代码在topLayoutGuide.length内以模态方式显示UIViewController

UINavigationController

关于let viewController = UIViewController(nibName: "ViewController", bundle: nil) let navigationController = UINavigationController(rootViewController: viewController) present(navigationController, animated: true, completion: nil)

的调试输出
topLayoutGuide.length

现在我在视图控制器中使用bool标志只在Init view controller -[UIViewController topLayoutGuide]: guide not available before the view controller's view is loaded willMove toParentViewController - top layout guide nan Init navigation controller and pass view controller as root vc Present navigation controller modally viewDidLoad - top layout guide 0.0 viewWillAppear - top layout guide 0.0 viewWillLayoutSubviews - top layout guide 64.0 viewDidLayoutSubviews - top layout guide 64.0 viewWillLayoutSubviews - top layout guide 64.0 viewDidLayoutSubviews - top layout guide 64.0 viewDidAppear - top layout guide 64.0 didMove toParentViewController - top layout guide 64.0 viewWillLayoutSubviews - top layout guide 64.0 viewDidLayoutSubviews - top layout guide 64.0 中设置一次contentoffset,即使该方法被多次调用。

还有更优雅的解决方案吗?

1 个答案:

答案 0 :(得分:3)

documentation for the topLayoutGuide明确声明:

  

finally()方法的实现中查询此属性。

从您自己的检查来看,获得viewDidLayoutSubviews()实际长度的最早点是topLayoutGuide方法。但是,我不会依赖于此,并按照文档建议的那样在viewWillLayoutSubviews()中执行此操作。

您之前无法访问该属性的原因......

...布局指南是依赖于任何容器视图控制器布局的对象。在屏幕上需要时,这些视图会被懒散地布置。因此,当您将viewDidLayoutSubviews()添加到viewController作为其根视图控制器时,它尚未布局。

当您展示navigationViewController时,会发生布局。此时,将加载两个视图控制器的视图(→navigationControllerviewDidLoad()),然后触发布局传递。首先,列出viewWillAppear()的视图(布局流程:superview→subview)。导航栏的框架设置为64像素的高度。现在可以设置navigationViewController的{​​{1}}。最后列出了viewController的视图(→topLayoutGuideviewController)。

结论:

根据布局指南的长度进行某些初始布局调整的唯一方法是您自己建议的方法:

  1. 在您最初设置为viewWillLayoutSubviews()的视图控制器中有一个布尔属性:

    viewDidLayoutSubviews()
  2. true内检查该属性,并仅在var isInitialLayoutPass: Bool = true 时执行初始布局:

    viewDidLayoutSubviews()
  3. true内,将属性设置为func viewDidLayoutSubviews() { if isInitialLayoutPass { tableView.contentOffset = CGPoint(x: 0, y: topLayoutGuide.length) } } ,表示初始布局已完成:

    viewDidAppear()
  4. 我知道它仍然感觉有点hacky但我担心这是唯一的方法(我能想到的),除非你想使用键值观察(KVO)在我看来,它并没有让它更整洁。