0

I had a conversation with my colleagues about setNeedsLayout() and layoutIfNeeded().

Starting from the conclusion, my colleague says setNeedsLayout() 'may' or 'should' be called before layoutIfNeeded(), because layoutIfNeeded() may not conduct layout if we don't set the 'layout flag' to true by calling setNeedsLayout(). Whereas, my thought is, calling both of them in the same place will lead to the same result as we call layoutIfNeeded() only. Because...

What I know about them is, as described here and here, setNeedsLayout() is just invalidating the current layout and then the coming update cycle would take care of the rest. layoutIfNeeed() is updating the layout immediately, so don't want to the coming update cycle.

Simply saying, async call and sync call. And that's it.

If there is no animation, I don't recall I've seen a lot of cases I had to use layoutIfNeeded(Perhaps one or two). Most of the cases, it worked quite well only with setNeedsLayout(). Moreover, if there is a case that needs to call both of them in the same place, I would rather say it's a bug from UIKit.

Can someone explain me which one is correct, and why?

Ramesh Sanghar
  • 174
  • 1
  • 1
  • 19
maybeiamme
  • 134
  • 1
  • 5
  • Does this answer your question? [setNeedsLayout vs. setNeedsUpdateConstraints and layoutIfNeeded vs updateConstraintsIfNeeded](https://stackoverflow.com/questions/20609206/setneedslayout-vs-setneedsupdateconstraints-and-layoutifneeded-vs-updateconstra) – Ramesh Sanghar Sep 30 '22 at 04:44
  • also this might be helpful : https://abhimuralidharan.medium.com/ios-swift-setneedslayout-vs-layoutifneeded-vs-layoutsubviews-5a2b486da31c – Ramesh Sanghar Sep 30 '22 at 04:50
  • Thanks @RameshSanghar, I already visited that article. I can get the conclusion from the most voted answer, but I still could find a different opinion with a decent number of votes below it. That's what makes me confusing :) – maybeiamme Sep 30 '22 at 04:58
  • from most of sources it looks like layoutIfNeeded forces an immediate update of the layout and setNeedsLayout asks for a layout update on a particular view, which will take place on the next update cycle. other then that there's no significant difference between two and setNeedsLayout is not required before calling layoutIfNeeded. – Ramesh Sanghar Sep 30 '22 at 05:51
  • 1
    I think [this](https://medium.com/@linhairui19/difference-between-setneedslayout-layoutifneeded-180a2310e2e6) article covers it pretty much with example of a corner case. TL:DR - `setNeedsLayout()` *may* have side effects on `layoutIfNeeded()` in the current update cycle. Thus you better use it if you want to be safe – The Dreams Wind Sep 30 '22 at 07:32

1 Answers1

3

First, a little discussion what these methods do, the answer to your question is below that.

From the documentation of setNeedsLayout():

This method makes a note of the request and returns immediately. Because this method does not force an immediate update, but instead waits for the next update cycle, you can use it to invalidate the layout of multiple views before any of those views are updated.

Usually, you need to call this if there's some external factor affecting the layout that UIKit doesn't know about (e.g. old fashioned manual layouting code by overriding layoutSubviews()). It doesn't trigger an immediate re-layout, that usually only happens on the next main runloop iteration. This allows you to mark several views as needing layouts, you can call it on the same view multiple times within the same runloop iteration, but UIKit only does the actual layouting once (as I just noted, usually on the next runloop iteration).

But if you need the layout to get settled right now (e.g. because you need to measure its result), you need to call layoutIfNeeded().

If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.

This is a crucial point about layoutIfNeeded(): if the layout system doesn't know there are pending changes, it simply won't do any. Calling setNeedsLayout() is the way we tell the layout system that there are changes that require a layout run.

If you only use auto-layout and manipulate just the constraints of the view you are about to re-layout, you can skip setNeedsLayout() since that has already been called indirectly; but setNeedsLayout() is very cheap, so there's no harm in calling it if you're unsure.


So, after calling setNeedsLayout(), do you need to call layoutIfNeeded()? To simply update the view on screen, no, you do not need to call layoutIfNeeded() since UIKit will do so on its own on the next main runloop iteration. In fact, you might negatively impact render performance if you always call layoutIfNeeded() even though your code doesn't need the updated layout right away since this can result in multiple layouting runs within the same runloop iteration.

But if you rely on the layout information immediately (for example, you need to measure the height of a view), you do need to call it. Just beware to have your design not do this too often.

Your comparison with "async" and "sync" is indeed somewhat fitting: in a way, you can see setNeedsLayout() as triggering an asynchronous operation and layoutIfNeeded() "waits" until it has happened (that's not what's actually going on, but from a certain point of view that is the observable effect).

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • `So, after calling setNeedsLayout(), do you need to call layoutIfNeeded()?` i believe the OP asks the other way around - **Whether `setNeedsLayout()` is necessary before calling `layoutIfNeeded()`?**. IIRC any updates to constraints invalidate all layouts in the affected hierarchy implicitly, but not all parts of `UIKit` rely on constraints (sometimes it's still old-fashioned frame update), let alone custom views. Your answer still holds, however - *yes, but only if you expect the changes to apply in the current update cycle*, because otherwise changes may remain unnoticed until future cycles – The Dreams Wind Sep 30 '22 at 07:28
  • @TheDreamsWind: The second-to-last paragraph of OPs question suggests "do you need `layoutIfNeeded()`, other parts suggest what you mentioned. I tried to address both, the paragraph starting with "If you only use auto-layout …" mentions what you clarified as well; thanks. – DarkDust Sep 30 '22 at 08:56