调用setNeedsLayout或setNeedDisplay的机会

时间:2018-05-18 07:48:13

标签: ios swift

我已经阅读了一些文章,说明setNeedsLayout和layoutIfNeeded之间有什么区别,而我关注的是:

1。如果我想立即布局,我是否需要将这两种方法一起调用,因为我多次看到这种组合

2。我什么时候需要调用setNeedsLayout?根据我的理解,如果我更改视图的框架,它将在下一个周期更新布局,我不必显式调用setNeedsLayout

2 个答案:

答案 0 :(得分:3)

这些工作如何工作是通过失效来删除冗余。如果需要布局,视图将包含信息。

因此调用setNeedsLayout只会将一些内部布尔值needsLayout设置为true。调用layoutIfNeeded后,它将检查此布尔值

if needsLayout { 
    needsLayout = false
    doMagic() // Calls layoutSubviews at some point
}

为什么设计这种方式是因为多次调用可能会使布局无效,但我们只希望将其布局一次或尽可能少的布局。

在大多数情况下,您无需致电setNeedsLayout,因为大多数更改已经为您执行了此操作。例如,您可以更改约束值并为您完成失效。您只需致电layoutIfNeeded,您的观点就会更新。为了更加正确,您甚至不需要拨打layoutIfNeeded,因为它会在下一个周期为您执行此操作。但是如果你想让动画更改动画,你需要调用它,你需要在动画块中做到这一点。

myViewConstraint.constant = 40.0 // Will already call setNeedsLayout
UIView.animate(withDuration: 0.3, animations: {
    myView.layoutIfNeeded()
})

因此,更改约束只会改变有关视图应如何布局的信息。只有对layoutIfNeeded的调用才会实际使用这些值并更改布局。这就是为什么你只需要把它放在动画块中(尽管把它全部放在块中也没错)。

公平地说,现在默认情况下会有一些变化(你可以禁用它)动画方法已经自己布局你的视图,所以你可以用更少的代码来做,但这不是现在的重点。

所以:

  1. 您无需一起调用2个方法即可进行布局。如果视图布局已经失效(在大多数情况下是这样),那么layoutIfNeeded就足够了。但请注意setNeedsLayout与将内部布尔值设置为true一样简单,因此调用它没有任何害处,只是一种预防措施。所以调用两者都更安全。单独拨打setNeedsLayout将不会做任何事情"立即"虽然。

  2. 希望您永远不需要致电setNeedsLayout。在某些复杂的情况下,您需要显式地使布局无效,并且存在一些可能的UI错误。在所有其他情况下,这将为您完成。但请注意,如果您遇到需要调用此情况的情况,它将在下一个周期更新布局"不会是真的。在视图布局无效之前,它根本不会布局。

  3. 我不确定setNeedDisplay在你的问题中的位置(仅在你的标题中),但这个方法的工作方式相同,但有点复杂。它会使其内容无效并强制重绘,请致电drawRect。这必须在其绘制管道中发生,而不是随时发生,因此您可能不会显式调用它来重绘。如果你什么都不做就会发生(也许会崩溃),因为它没有任何上下文可供使用。如果您覆盖drawRect并调整视图大小,则会尝试缓存您绘制的内容并使用contentMode调整图形大小。默认情况下,它设置为scaleToFill,这意味着您的内容将随着视图大小的变化而延长。您需要致电setNeedDisplay,以便再次调用drawRect,然后您可以相应地重新绘制内容。

答案 1 :(得分:0)

我找到了我想问的问题,什么时候应该调用setNeedLayout,什么时候不应该。因为调用setNeedLayout的目的是调用layoutSubviews,所以对于以下情况,我不必调用setNeedLayout

  • 调整视图大小
  • 添加子视图用户
  • 滚动UIScrollView
  • (在UIScrollView及其超级视图上调用layoutSubviews)
  • 用户旋转设备
  • 更新视图的约束