setNeedsLayout vs. setNeedsUpdateConstraints and layoutIfNeeded vs updateConstraintsIfNeeded

扶醉桌前 提交于 2019-11-26 21:12:30
coverback

Your conclusions are right. The basic scheme is:

  • setNeedsUpdateConstraints makes sure a future call to updateConstraintsIfNeeded calls updateConstraints.
  • setNeedsLayout makes sure a future call to layoutIfNeeded calls layoutSubviews.

When layoutSubviews is called, it also calls updateConstraintsIfNeeded, so calling it manually is rarely needed in my experience. In fact, I have never called it except when debugging layouts.

Updating constraints using setNeedsUpdateConstraints is pretty rare too, objc.io–a must read about autolayouts–says:

If something changes later on that invalidates one of your constraints, you should remove the constraint immediately and call setNeedsUpdateConstraints. In fact, that’s the only case where you should have to trigger a constraint update pass.

In addition, in my experience, I have never had to invalidate constraints, and not set the setNeedsLayout in the next line of the code, because new constraints pretty much are asking for a new layout.

The rules of thumb are:

  • If you manipulated constraints directly, call setNeedsLayout.
  • If you changed some conditions (like offsets or smth) which would change constraints in your overridden updateConstraints method (a recommended way to change constraints, btw), call setNeedsUpdateConstraints, and most of the time, setNeedsLayout after that.
  • If you need any of the actions above to have immediate effect—e.g. when your need to learn new frame height after a layout pass—append it with a layoutIfNeeded.

Also, in your animation code, I believe setNeedsUpdateConstraints is unneeded, since constraints are updated before the animation manually, and the animation only re-lays-out the view based on differences between the old and new ones.

Kunal Balani

The answer by coverback is pretty correct. However, I would like to add some additional details.

Below is the diagram of a typical UIView cycle which explains other behaviors:

  1. I've found out that if I use -setNeedsLayout instead of -setNeedsUpdateConstraints everything work as expected, but if I change -layoutIfNeeded with -updateConstraintsIfNeeded, the animation won't happen.

updateConstraints typically doesn't do anything. It just resolves constraints it doesn't apply them till layoutSubviews is called. So animation does requires a call to layoutSubviews.

  1. setNeedsLayout calls also -updateContraints method

No this is not necessary. If your constraints haven't been modified UIView will skip call to updateConstraints. You need to explicitly call setNeedsUpdateConstraint to modify constraints in the process.

In order to call updateConstraints you need to do the following:

[view setNeedsUpdateConstraints];
[view setNeedsLayout]; 
[view layoutIfNeeded];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!