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

时间:2017-02-23 02:17:35

标签: uiview uiviewcontroller autolayout layoutsubviews viewdidlayoutsubviews

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

注意:

  1. 视图的布局代码需要在任何父视图布局,方向更改,特征更改等后使用其框架尺寸
  2. 我曾尝试在父视图控制器上使用viewWillLayoutSubviews但有时难以多次调用它 - 无法追踪为什么不希望不得不多次进行手动布局计算很麻烦。
  3. 总而言之,对于下面的各种场景来说,只有一个单一的"触发"手动布局和所有旋转时的布局和父视图布局已完成:
  4. 所以:

    • on load(viewDidLoad)
    • 重新显示(视图后来确实出现)
    • 旋转
    • 特质改变

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

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

    b)将子视图留在" layoutSubview()"然后让一个代表可以回叫主控制器来请求布局数据?或

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

    或其他?

    实际上,我正在考虑这个想法:

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

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

1 个答案:

答案 0 :(得分:2)

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

  

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

UIView实现中只有一个地方应放置任何布局代码,并且位于方法layoutSubviews()内。

布局引擎(根据约束计算实际帧的内容)在 之后调用此方法它为此特定视图计算了正确的帧。换句话说:layoutSubviews()是布局过程中唯一可以确保视图已经具有正确框架集的位置。

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

但是,系统只会根据需要经常调用layoutSubviews()(除非您反复手动触发),即当前布局无效时。造成这种情况的原因可能有很多:设备轮换,约束更改,视图层次结构中的更改等。但这些是您的视图框架可能更改的情况如果您的自定义布局取决于该框架,那么 也应重新计算。

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

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