systemLayoutSizeFitting returns height 0

I've got a custom view that is full of child views, and those child views are constrained to the top/left/bottom/right of the parent view. I then put that custom view inside of a scroll view. When I look at the view, the entire thing is drawn properly, so my constraints all seem to be correct for position and sizing.


However, in the view controller that the scroll view is in, when I call systemLayoutSizeFitting against that custom view, it's giving me a width, but the height says 0. That makes is so I can't scroll vertically.


I'm not sure how to debug this to figure out what's going on. The fact that is says 0 for height makes me think that somehow it can't follow from top to bottom, but if it couldn't, then all the child views would be in the right locations with the right heights.

Answered by Claude31 in 256445022

I understand better what you are doing. But difficult to analyze without seeing the whole thing. So, let us guess.


It is always more difficult to debug when there are a lot of objects.


May be the child views in custom view are creating constraints that lead to set the height to zero.

One way to test would be to keep (for the test) only one subview in custom view ;

set top and bottom constraints let say to 20 and the child view height to 40.


And see what is the result.


What sometimes happen in these situations is that you have to change the priority of some constraints (900 vs 1000) so that autolayout manages it correctly.

You don't have any message in the log about autolayout ?

Just to make sure I follow correctly: the view hierarchy is nom

parent view (A) contains scroll view (B) contains custome view (C) contains child views(Ds). Right ?

Initially, hierarchy was:

parent view (A) contains custome view (C) contains child views(Ds). Still right ?


When you move the view C inside the scrollView B, are you sure you kept the constraints defined for C (relative to what ? initial parent view A or scroll view B).


If I were you, I would try to delete the initial constraints of C and recreate relative to scroll view B. Probably, I would have to create constraints for the scroll view B also with respect to the parent view A.

So I've created my hierarchy like so:


override func viewDidLoad() {
    super.viewDidLoad()

    scrollView = UIScrollView(frame: view.bounds)
    scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    scrollView.delegate = self

    bracketsView = BracketView(bracket: bracket)

    scrollView.addSubview(bracketsView)
    view.addSubview(scrollView)

    NSLayoutConstraint.activate([
        bracketsView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
        bracketsView.topAnchor.constraint(equalTo: scrollView.topAnchor)
    ])


I'm not quite following what you are suggesting I do, so maybe seeing the above will make it clearer? The BracketView class is what you were calling C, and in its constructor it creates all the child view D elements and sets all their constraints.

Accepted Answer

I understand better what you are doing. But difficult to analyze without seeing the whole thing. So, let us guess.


It is always more difficult to debug when there are a lot of objects.


May be the child views in custom view are creating constraints that lead to set the height to zero.

One way to test would be to keep (for the test) only one subview in custom view ;

set top and bottom constraints let say to 20 and the child view height to 40.


And see what is the result.


What sometimes happen in these situations is that you have to change the priority of some constraints (900 vs 1000) so that autolayout manages it correctly.

You don't have any message in the log about autolayout ?

Thanks, Claude31. I did what you said, just on a slightly larger scale, and it worked perfectly, so I went back and looked closer at my full code. All the constraints were 100% correct, except I found I was setting a couple of them and not pushing them into the array that got activated, so it was there, but not actually turned on. Once I moved them all into the array of constraints I was building up, it worked perfectly. Phew! This was driving me insane.

Debugging constraints is always a bit of a nightmare.


What I do now, when I have a lot of constraints, is to give an ID to each (just a number as #C01, in the order they appear in IB). That eases a bit debugging by giving a clear identification when autolayout logs in debugger. That would not have been useful here, but may help in many cases.

systemLayoutSizeFitting returns height 0
 
 
Q