How to set a custom view's intrinsic content size in Swift?

IosSwiftCustom ControlsIntrinsic Content-Size

Ios Problem Overview


Background

I am making a vertical label to use with traditional Mongolian script. Before I was just rotating a UILabel but there were some performance issues and other complications with this. Now I am working on making a label from scratch. However, I need the vertical label to tell auto layout when its height adjusts (based on string length).

What I have read

I read the Intrinsic Content Size and Views with Intrinsic Content Size documentation. These were more about how to use it, though, and not how to define it in a custom view.

Searching for "ios intrinsic content size for a custom view" only gives me

in Stack Overflow. This particular question didn't even need intrinsic content size because their view was just an assembly of standard views.

What I am trying

What I am trying is my answer below. I am adding this Q&A pair so that it won't take other people as long to find the answer as it took me with the search keywords that I used.

Ios Solutions


Solution 1 - Ios

Setting the intrinsic content size of a custom view lets auto layout know how big that view would like to be. In order to set it, you need to override intrinsicContentSize.

override var intrinsicContentSize: CGSize {
   return CGSize(width: x, height: y)
}

Then call

invalidateIntrinsicContentSize()

Whenever your custom view's intrinsic content size changes and the frame should be updated.

Notes

Solution 2 - Ios

Example of a "view with intrinsic height" ...

@IBDesignable class HView: UIView {

    @IBInspectable var height: CGFloat = 100.0

    override var intrinsicContentSize: CGSize {
        return CGSize(width: 99, height: height)
        // if using in, say, a vertical stack view, the width is ignored
    }

    override func prepareForInterfaceBuilder() {
         invalidateIntrinsicContentSize()
    }
}

enter image description here

which you can set as an inspectable

enter image description here

Since it has an intrinsic height, it can (for example) be immediately inserted in a stack view in code:

stack?.insertArrangedSubview(HView(), at: 3)

In contrast, if it was a normal view with no intrinsic height, you'd have to add a height anchor or it would crash:

let v:UIView = HView()
v.heightAnchor.constraint(equalToConstant: 100).isActive = true
stack?.insertArrangedSubview(v, at: 3)

Note that in ...

the important special case of a stack view:

  • you set only ONE anchor (for vertical stack view, the height; for horizontal the width)

so, setting the intrinsic height works perfectly, since:

  • the intrinsic height indeed means that the height anchor specifically will be set automatically if needed.

Remembering that in all normal cases of a subview, many other anchors are needed.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSuragchView Question on Stackoverflow
Solution 1 - IosSuragchView Answer on Stackoverflow
Solution 2 - IosFattieView Answer on Stackoverflow