Q:

Update frame of UIView with label in it after changing label's contents

I have a custom view which contains a label in it (assume the label is pinned to all the edges of the view). The width of the custom view depends on the text property (naturally, the longer the text the longer the view is going to be).
However, an issue arises. When I instantiate let customView = CustomView() and then assign a new text to the label like customView.textLabel.text "New text", the frame of the custom view is still zero. I think this is because I didn't set a frame at the beginning.
If I decide to set an initial frame at init time (let customView = CustomView(CGFrame(...))) and then update the label content, the frame does not change its width. Why? How can I have a dynamic view that adapts its frame to its content? Calling sizeToFit on the label or view does not change the frame.

A:

How can I have a dynamic view that adapts its frame to its content? 

The usual thing is to position the view with auto layout and override intrinsicContentSize to supply the width and height based on the content views (such as the label). The auto layout engine will obey the intrinsicContentSize automatically.
Note that the intrinsic content size doesn't magically know its own dependencies; it's up to you call invalidateIntrinsicContentSize whenever you change a dependency (such as the text of the label), so that intrinsicContentSize is called again to recalculate the height and width.
In this example, CustomView is the red view, and the label inside it with a white background is its textLabel. Note how the red view automatically expands and contracts in synchrony with the automatic expansion and contraction of the label as the label's text changes.

This is a very simple example for purposes of illustration, so my implementation of CustomView is very simple:
class CustomView : UIView {
    @IBOutlet var textLabel : UILabel!
    override var intrinsicContentSize: CGSize {
        let w = self.textLabel.intrinsicContentSize.width + 40
        let h = self.textLabel.intrinsicContentSize.height + 40
        return CGSize(width: w, height: h)
    }
}

And now the buttons just say this sort of thing:
    self.customView.textLabel.text = // whatever
    self.customView.invalidateIntrinsicContentSize()

