使用基于框架的布局桥接自动布局

您是否曾经遇到过将新的基于“自动布局”的视图放置在一些较旧的基于框架的代码中的问题? 您将遇到的一个问题是,您需要一种方法使基于框架的布局知道其“自动布局”子视图的大小何时更改。 事实证明,这可以很简单地解决! 在本文中,我将介绍一个示例以及解决方案。

让我们从一个示例开始:我们的父UIViewController创建一个AutoViewController其大小由“自动布局”约束定义。 在内部,我们的AutoViewControllerUILabel绑定到其边缘。 随着文本行数的更改, AutoViewController将扩展以适应这种情况。

 私人让autoVC = AutoViewController() 
 覆盖func viewDidLoad(){ 
super.viewDidLoad()
addChildViewController(autoVC)
view.addSubview(autoVC.view)
}

我们需要一种找到AutoViewController大小的方法,以便我们可以设置其框架。 使用UIView上的systemLayoutSizeFitting(targetSize:)方法,我们可以获得由自动布局定义的子视图的高度。 在我们的例子中,我们希望视图在父级中显示为固定宽度的行,因此我们定义了一种获取尺寸的方法。 我们提供了可用的宽度,但要求压缩的高度-否则,我们的“自动版式”视图可以自由地垂直拉伸超过其所需的水平,以填满父级。

 私人功能rowSize(forView视图:UIView)-> CGSize { 
返回view.systemLayoutSizeFitting(
CGSize(width:view.bounds.width,
高度:UILayoutFittingCompressedSize.height)

}

然后,我们可以使用此方法设置基于“自动布局”视图的框架。 尽管不是严格要求,但是我们在父级布置其子视图时执行此操作。 最终,该视图将成为更复杂的基于框架的布局的一部分,因此,如果更改,其兄弟视图也可能需要调整。 viewWillLayoutSubviews()是一个很好的安排。

 覆盖func viewWillLayoutSubviews(){ 
让childFrame = CGRect(
原点:.zero,
大小:rowSize(forView:autoVC.view)

autoVC.view.frame = childFrame
}

我们仍然有问题。 我们基于自动布局的子UIViewController可能会更改其大小。 看起来像这样:

值得庆幸的是,Apple为我们提供了一种了解何时发生这种情况的方法。 通过处理systemLayoutFittingSizeDidChange(forChild:)我们可以对此做出响应。 在这里,我们将父视图标记为需要进行布局的布局,因为我们的子框架是在viewWillLayoutSubviews中设置的,因此可以完成此操作。

 覆盖func systemLayoutFittingSizeDidChange(forChildContentContainer:UIContentContainer){ 
view.setNeedsLayout()
}

而已! 我喜欢这个解决方案,因为它避免让您的UIView / UIViewController类将大小更改显式地传达给其父级-这种方法通常容易出错,并且可能导致无限次布局通过。