How does addSubview work with intrinsicSizes?
Asked Answered
F

2

0

The result of the following code is: I don't see the label.

My understanding was that the intrinsicSize of the label would allow the label to stretch . Why isn't that happening?

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(label)
    }

    let label : UILabel = {
        let label = UILabel()
        label.text = "How are you doing today my friend"
        label.backgroundColor = .orange

        return label
    }()
}
Flores answered 22/12, 2017 at 21:50 Comment(6)
No frame layout or auto layout set for the labelBluejacket
@Sh_Khan Based on Auto Layout Guide, intrinsicSize. See Listing 3-5Compression-Resistance and Content-Hugging equations. IntrinsicSize generate constraints... Even if I set the translatesAutoresizingMaskIntoConstraints to false I still get the same result...Flores
Check the layout debugger, see where it's located and what the frame is.Shadshadberry
@Shadshadberry I already did that, obviously the frame is 0,0,0,0Flores
You haven't set any constraints. Autolayout will use intrinsic size but you still need to give it some clue where you want the labelUnchurch
Then you may want to rephrase your question to "The result of the following is: the frame is 0", not "The result of the following code is: I don't see the label."Shadshadberry
W
1

This:

let label = UILabel()

creates a label at (0, 0) with width 0 and height 0. By default, iOS will create constraints from the frame for the position, width, and height of the label.

If you want to use the intrinsic size of the label, disable the creation of constraints from the frame and give the label constraints to place it in the view.

For example (after adding the label as a subview):

label.translatesAutoresizingMaskIntoConstraints = false
label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Or you can use the label.intrisicContentSize when you create frame:

label.frame = CGRect(origin: CGPoint(x: 40, y: 100), size: label.intrinsicContentSize)

Note: If you use label.intrinsicSize to set the frame, the frame will not change when you change the label text. You'd have to update it again with:

label.frame.size = label.intrinsicContentSize

after changing label.text.


In reality, Auto Layout creates 4 constraints for a label's instrinsicContentSize, but these constraints are at a lower priority than the constraints created from the frame, so they have no effect. By disabling the creation of constraints from the frame, you give the lower priority instrinsicContentSize constraints an opportunity to affect the layout of the UILabel.

You can read about this in more detail in Apple's Auto Layout Guide in the section entitled Intrinsic Content Size.

Washedout answered 22/12, 2017 at 22:24 Comment(11)
"creates a label at (0, 0) with width 0 and height 0." correct. So how does centering it give it a height and width?! To me it should only change the x & y... Your usage of label.intrinsicContentSize is awesome. I really liked that.Flores
Auto Layout gives it the width and height using the intrinsicContentSize if you don't give it constraints explicitly specifying the width and height.Washedout
If you don't set label.translatesAutoresizingMaskIntoConstraints = false, then iOS will create explicit constraints for the width, height, and position of the label from the frame which is (0, 0, 0, 0). This is why it isn't using the intrinsicContentSize, because the width and height are constrained to 0.Washedout
"If you don't set label.translatesAutoresizingMaskIntoConstraints = false, then iOS will create explicit constraints for the width, height, and position of the label from the frame" OK. But when you do set it, where does it get the width/height when you center it?! shouldn't the width and height stay 0? I don't see you setting the width and height, yet it works...Flores
No. Auto Layout's algorithm is: if label width and height are not specified with constraints, use the intrinsic content size. Setting label.translatesAutoresizingMaskIntoConstraints = false removes the 4 constraints created for you by the system and leaves everything unconstrained. By specifying the position for the label, iOS figures out the width and height from the intrinsicContentSize.Washedout
your last comment is the ultimate answer. That's what I'm experiencing. Would be great if you could provide a reference...Flores
@Honey, it's slightly more complicated that I wrote. The system creates constraints for the intrinsicContentSize, but these constraints are at a low priority and have no effect if they are overpowered by a higher priority constraint. The constraints created by default from the frame have high priority, so they don't give the instrinsicContentConstraints a chance to work. By disabling the constraints created from the frame, the lower priority intrinsicContentConstraits get a chance to work.Washedout
still thinking about this... Why after doing label.translatesAutoresizingMaskIntoConstraints = false and without setting any position the view debugger doesn't warn us of unambiguous position instead? I mean at this moment the high priority are disabled...but still we do have the constraints created by intrinsicSize...having the warnings would have made more sense don't you agree?Flores
It seems Auto Layout doesn't actually do anything until you explicitly add your first constraint.Washedout
If you override viewDidLayoutSubviews and print(view.constraints.count) and print(label.constraints.count) you'll see that there are 0 constraints if you just set label.translatesAutoresizingMaskIntoConstraints = false. But as soon as you set a Y position constraint, those counts go to 5 and 2. The 5 are the 4 instrinsicContentSize constraints plus the Y position constraint. The 2 are the constraints for the width and height of the label.Washedout
I learned a lot of interesting things from this discussion. Thank you so you muchFlores
B
0

It's Intrinsic content size not Intrinsic content position guarantee to give a width and height for the label If it's not rigidly have leading and trailing constraints that may trim it's content , but at least you must give the label x,y position either by frame layout or auto layout but to set

  translatesAutoresizingMaskIntoConstraints to false
Bluejacket answered 22/12, 2017 at 22:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.