1

当父视图本身使用自动布局时,我拥有的特定子 UIView 应该在哪里放置手动布局代码(或在哪里触发它)?

笔记:

  1. 视图的布局代码需要在任何父视图布局、方向更改、特征更改等之后使用其框架尺寸
  2. 我曾尝试在父视图控制器上使用 viewWillLayoutSubviews,但在多次调用它时遇到困难 - 无法追查为什么但不想多次手动布局计算,因为它们很繁重。
  3. 因此,总体而言,对于以下各种场景,最终只有一个手动布局的“触发”,并且在所有旋转和父视图布局完成时:

所以:

  • 加载时 (viewDidLoad)
  • 重新显示(就像视图随后确实出现了)
  • 回转
  • 性状改变

例如,我应该寻找一种方法:

a)父视图控制器来控制它并确定何时向我的特定子视图(由它自己的视图控制器前置)发送“layoutSubviewNow”调用,但在这种情况下如何执行此操作,或 b)

b)让子视图对“layoutSubview()”做出反应,然后有一个委托可用于回调主控制器以请求布局数据?或

c) 类似于 b) 但使用子视图视图控制器“viewWillLayoutSubviews()”来触发,然后有一个委托可用于回调主控制器以请求布局数据?

或其他?

其实我在想这个主意:

d) 在主父视图控制器中:有一个实例变量 viewTransistionedOutstandingAction,并使用它以便 (i) 在 vi​​ewWillTransition 中将其设置为 true,然后在 (ii) viewWillLayoutSubviews 中执行以下操作:

if viewTransistionedOutstandingAction {
  self.triggerModelChange()
  viewTransistionedOutstandingAction = false
}
4

1 回答 1

3

我有点不清楚您的具体要求是什么,但我可以为您的第一个问题提供答案:

当父视图本身使用自动布局时,我拥有的特定子 UIView 应该在哪里放置手动布局代码(或在哪里触发它)?

UIView实现中只有一个地方应该放置任何布局代码,那就是方法内部layoutSubviews()

布局引擎(根据你的约束计算实际帧的东西)在它为这个特定的视图计算出正确的帧之后立即调用这个方法。换句话说:layoutSubviews()是布局过程中唯一一个可以确保视图已经设置正确的框架的地方。

您是正确的,此方法可能不仅会被调用一次,而且会被调用多次。这是因为在某些情况下,需要多次布局传递来计算最终布局。(示例:您有一些视图,其高度取决于其父视图的宽度,但父视图的高度取决于子视图的高度。)layoutSubviews()也可以从代码中手动调用该方法,例如在视图上调用setNeedsLayout()后跟layoutIfNeeded()将导致layoutSubviews()对该视图的调用也是。

但是,系统layoutSubviews()仅在需要时调用(除非您一次又一次地手动触发它),即每当当前布局无效时。造成这种情况的原因有很多:设备旋转、约束更改、视图层次结构的更改等。但在这些情况下,您的视图框架可能会发生变化,如果您的自定义布局依赖于该框架,它实际上也应该重新计算。

出于这个原因,这layoutSubviews()是执行手动布局的正确位置,您应该避免在其他任何地方执行此操作。


注意:如果您正在处理视图控制器而不是普通视图,则执行布局更新的相应方法是viewWillLayoutSubviews()(或者viewDidLayoutSubviews()如果您使用自动布局并且只想在布局引擎解决所有子视图的约束后进行轻微修改) .

于 2017-03-01T23:23:41.010 回答