父视图使用自动布局的 UIView 的手动布局代码放在哪里?

where to put manual layout code for a UIView where parent views use autolayout?

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

备注:

  1. 在任何父视图布局、方向更改、特性更改等之后,视图的布局代码需要使用其框架尺寸
  2. 我曾尝试在父级 viewcontroller 上使用 viewWillLayoutSubviews,但在多次调用它时遇到困难 - 无法找出原因,但不想再进行手动布局计算不止一次,因为它们很繁重。
  3. 总的来说,针对以下各种情况的一种方法最终只有一个 "triggering" 手动布局,并且在完成所有旋转和父视图布局后:

所以:

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

a) 父视图控制器来控制它并确定何时向我的特定子视图发送 "layoutSubviewNow" 调用(它前面是它自己的 viewcontroller),但在这种情况下如何这样做,或者 b)

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

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

或其他?

其实我在想这个主意:

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

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

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

Where to put manual layout code (or where to trigger it) for a specific child UIView I have, when the parent views themselves utilise autolayout?

UIView 实现中只有一个地方可以放置任何布局代码,那就是方法 layoutSubviews().

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

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

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

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


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