flowkey/UIKit-cross-platform

On `sizeToFit()` call `sizeThatFits()` of each subview

rikner opened this issue · 2 comments

We have some behaviour differences between UIKit cross platform and Apple's UIKit relating to sizeToFit and layoutSubviews.

In our app, we add some sizeToFit calls on cross-platform that don't need to be there on iOS. Specifically, when calling sizeToFit of a UIView that contains subviews, iOS seems to automatically call sizeToFit on the subviews first, before calling it on the parent. In cross-platform, we have to call sizeToFit manually on the subviews first. The flip-side of this is that our iOS app (that uses the same code) is probably doing more work than it needs to.

What I'm not sure on is what level iOS checks the children's sizes on: whether this happens at the level of sizeThatFits -> the children are checked for their individual sizeThatFits which is then set on the parent, or whether sizeToFit just calls sizeToFit on the children first before returning. The difference is whether calling sizeThatFits on the parent is enough to get the right size, or whether the parent's size is only correct after calling sizeToFit. Another question is whether calling sizeToFit on the parent actually sizes the children as well.

Would be nice to investigate, fix, and test this thoroughly.

janek commented

OK, I started looking into this but it's pretty broad, so I'm only addressing a small thing in this comment first: I noticed that we have the following default implementation of layoutSubviews in UIView in cross-platform:

open func layoutSubviews() {
        needsLayout = false
        subviews.forEach { $0.setNeedsLayout() }
}

While according to Apple, their default implementation:
(..) does nothing on iOS 5.1 and earlier. Otherwise, the default implementation uses any constraints you have set to determine the size and position of any subviews.
(https://developer.apple.com/documentation/uikit/uiview/1622482-layoutsubviews)

Which seems to mean, since we are not supporting constraints yet, our default implementation should be empty. Or is there a reason we're doing it differently?

can we close this? @rikner