(I'm posting this question as S.O. ("Answer your own question") format to make this recipe easy to find, and to get any other helpful perspectives).
Question: What is a convenient way to set a specific content size UIViews?
Use case driving the question:
I'm working with an app with many UIStackView instances that display custom icons next to each other.
The stack view items are often UILabel other times, simply UIView.
Apple Docs say UILabel is a type that sets its own intrinsic content size. And in many case that works out okay. However, for certain UILabel, instances, the intrinsic content size is not set optimally, which can be challenging for getting UIStackView to layout precisely.
In other cases, I create a UIView where it is not optimal to subclass each UIView I create, but rather render a CALayer into the view after the view's creation. Thus the UIView cannot set its intrinsic size properly. Thus, when I use that as an item in UIStackView, it sees the content CGSize as (0, 0), regardless of frame setting, and so UIStackView doesn't handle it properly even with spacing and custom spacing options.
Since I know the size of the layer whose graphics I'm rendering in advance, it would be helpful to be able to construct the UIView with a predetermined size, similarly to the way people generally construct UIView(frame: CGRectMake(x, y, w, h), but in a way UIStackView recognizes (e.g. intrinsic content size).
The OP and I briefly discussed this design and I pointed out some potential sources of ambiguity:
sizeand aframeand thatframecould have a different size (which is potentially useful but more likely a source of errors in my opinion). I suggested it should take anoriginand asize..zero.Having thought about it some more, here’s a few more things I think could be improved:
frame) initialiser saves the initial size, there isn’t really much value in having the convenience initialiser take an origin. Similarly, anyone wanting to specify a zero size could useinit()or specify a frame so the convenience initialiser could require asizewithout any loss of features.invalidateIntrinsicContentSize().The OP is obviously happy with their version and invited me to create my own answer. Here’s a version which addresses my comments: