iosswiftuikitcore-graphicsrunloop

is the frame after executing setNeedsLayout and layoutIfNeeded always get accurate view's frame?


My understanding is, after execute setNeedsLayout will mark the view as "dirty" so that in the next rendering cycle, the view will be be re-layout. layoutIfNeeded will force to trigger re-layout immediately if the view is marked as "dirty".

However, even layoutIfNeeded immediately start to layout, it does not mean that the code after layoutIfNeeded will be waiting until it finishes. The render part is an async operation, it will be handled by core graphic through runloop.

myView.setNeedsLayout()
myView.layoutIfneeded()
print(myView.frame)

My point is, the printing of frame above may not always get correct frame, since the render operation is an async task, am I right?

Some context:

  1. myView is render finished.
  2. one of its subview's height constraint get changed due to some async data task.
  3. execute above setNeedsLayout and layoutIfNeed like mentioned above.

Solution

  • am I right

    Yes. If you want the frame right now, either flush the current transaction or (perhaps better) allow a cycle by doing a zero-delay asyncAfter. See How to, simply, wait for any layout in iOS? (and probably I should just be closing this question as a dupe of that one).

    I should mention that an even better way is just to implement viewDidLayoutSubviews or layoutSubviews. That way, you arrive into the layout cycle at exactly the right moment to obtain any desired frame info.