Proper usage of intrinsicContentSize and sizeThatFits: on UIView Subclass with autolayout Proper usage of intrinsicContentSize and sizeThatFits: on UIView Subclass with autolayout ios ios

Proper usage of intrinsicContentSize and sizeThatFits: on UIView Subclass with autolayout


I don't think you need to define an intrinsicContentSize.

Here's two reasons to think that:

  1. When the Auto Layout documentation discusses intrinsicContentSize, it refers to it as relevant to "leaf-views" like buttons or labels where a size can be computed purely based on their content. The idea is that they are the leafs in the view hierarchy tree, not branches, because they are not composed of other views.

  2. IntrinsicContentSize is not really a "fundamental" concept in Auto Layout. The fundamental concepts are just constraints and the attributes bound by constraints. The intrinsicContentSize, the content-hugging priorities, and the compression-resistance priorities are really just conveniences to be used to generate internal constraints concerning size. The final size is just the result of those constraints interacting with all other constraints in the usual way.

So what? So if your "custom view" is really just an assembly of a couple other views, then you don't need to define an intrinsicContentSize. You can just define the constraints that create the layout you want, and those constraints will also produce the size you want.

In the particular case that you describe, I'd set a >=0 bottom space constraint from the label to the superview, another one from the image to the superview, and then also a low priority constraint of height zero for the view as a whole. The low priority constraint will try to shrink the assembly, while the other constraints stop it from shrinking so far that it clips its subviews.

If you never define the intrinsicContentSize explicitly, how do you see the size resulting from these constraints? One way is to force layout and then observe the results.

Another way is to use systemLayoutSizeFittingSize: (and in iOS8, the little-heralded systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority:). This is a closer cousin to sizeThatFits: than is intrinsicContentSize. It's what the system will use to calculate your view's appropriate size, taking into account all constraints it contains, including intrinsic content size constraints as well as all the others.

Unfortunately, if you have a multi-line label, you'll likely also need to configure preferredMaxLayoutWidth to get a good result, but that's another story...