0

So I recently was creating what Apple calls a leaf-level view (a button) and so I followed Apple's docs to implement -intrinsicContentSize and everything worked (albeit the code felt a bit weird - I had constraints set up in my -updateConstraints method to position subviews, as well as code in the -intrinsicContentSize method to calculate what the total size should be; it felt like I was giving duplicate information to the autolayout system).

However, I also ran into a post on here claiming to, instead of using -intrinsicContentSize, use rigid constraints and then the containerview will automatically resize to fit the views it contains. I also implemented this, and achieved the same result as above, but this time I didn't feel like I was duplicating information sent (I just sent the straight constraints). Note that I see the view as described in the post mentioned above as a so called leaf-level view since it doesn't sound like any other view would be added to it.

Which implementation of resizing a container view based on the content inside of it is the proper way to go?


I'm currently leaning towards the second method, due to the fact that I don't think I should be sending duplicate information, however Apple's documentation says otherwise (then again, Apple's docs can be a bit confusing/misleading at times).


Sidenote about my specific situation, f it matters: I have two subviews in my button, one being an image, the other being a label. The image gets it's size from the label, and then the entire button from the image (so indirectly the sizing comes entirely from the label).

Community
  • 1
  • 1
DanZimm
  • 2,528
  • 2
  • 19
  • 27
  • If your view has subviews, it isn't a leaf-level view. – Ken Thomases Jul 03 '15 at 20:14
  • @KenThomases fair point - I can easily use layers (which just takes away the non-leafyness from UIKit and puts it into QuartzCore, or use `-drawRect` to display my content), but the point I'm asking maintains a concern... – DanZimm Jul 03 '15 at 20:26
  • @KenThomases Also, for the record, Apple uses an example of a `button` as a leaf-level view, implying a `UIButton` is a leaf level view, but in `UIButton`'s docs theres an apparent `UILabel` (actually a `UIButtonLabel`) that is used to display text (which is a subview) – DanZimm Jul 03 '15 at 20:32
  • Those docs were originally written for OS X, as is evident from mentions of `NSView` and the screenshots. On OS X, buttons are not implemented in terms of subviews. More importantly, though, my point is that `-intrinsicContentSize` is about a size which is, well, intrinsic to the view and its "content", not extrinsic (derived from other views or its relationship to them). The very fact that your implementation was essentially redundant with internal constraints with subviews means it's not appropriate. – Ken Thomases Jul 03 '15 at 21:45
  • @KenThomases These are fair points, but I'm interested in how this should be done on iOS - sure I can try to follow the paradigm you outlined, but the way views operate on the two platforms is pretty different, and so this leads me to think that using the method you would use on OSX might not be the proper way to go about this. This button I'm creating does, in a sense, have an intrinsic size, I want it to be a certain size based off of the text within the button - I simply use subviews (or sublayers) for convenience, as it seems is proper in iOS. Should I use `-drawRect` if this is the case? – DanZimm Jul 04 '15 at 03:02

1 Answers1

2

Your button view should have internal constraints, based on the label and the image. These should be sufficient to give it the correct size. You don't need to implement intrinsicContentSize for that.

The button's superview does not and should not know or care what is going on inside the button. You don't directly reference the intrinsic content size, the layout system does, and if your button has the right internal constraints, it isn't necessary.

Intrinsic content size is there to allow a view to express its size as something at the very bottom of the view hierarchy, based on its display contents, such as the text in a label. Everything above that is based on constraints.

You can also use it to allow a view with non-autolayout subviews to participate in autolayout, but this can lead to a lot of duplicated frame calculation code.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • 1
    The one thing I would add is that the button should propagate the content hugging and compression resistance priorities that are set on it to the subviews in the appropriate manner, so the "client" gets the appropriate behavior. – Ken Thomases Jul 04 '15 at 14:05