Search code examples
iosswiftuiviewuiviewcontrollernslayoutconstraint

Complex UIView lays out differently if I have IBOutlet for constraint


In the screen shots below, the only change I have made is to connect an IBOutlet for a constraint. Unconnected, screen lays out correctly. Connected, the screen lays out incorrectly. I have not seen this happen before and don't know what to try to fix it. I need to be able to modify the constant value of the constraint in order to resize a subview depending on the presence or absence of a particular item.

The IBOutlet is declared as:

@IBOutlet weak var tabContentBottomConstraint: NSLayoutConstraint!

So far, I have not implemented any code that reads or modifies this constraint. I added it to my view controller in preparation for using it, but have not gone any further because when I run the code after adding the IBOutlet, the view sizes incorrectly. I have added and removed several times, always with the same result.

Here is the debugger info on the view sizings prior to connecting the outlet:

enter image description here

And here is the debugger info after connecting the IBOutlet with no other code change whatsoever:

enter image description here

The difference in y offset is huge and pushes the view off the screen. As I said above, no code reads or writes to that IBOutlet.

The rolePageDrawerView is item2 in the constraint, and item1 is the view controller's view.safeAreaLayoutGuide. rolePageDrawerView is embedded 3 levels deep into child views of view.safeAreaLayoutGuide.


Solution

  • I found a way to work around this weird behavior by programmatically searching out the constraint with the following code:

        guard let tabContentBottomConstraint = view.constraints.filter({ $0.secondItem! as! NSObject == rolePageTabContentView }).first else {
            fatalError("unable to find the constraint for drawer sizing")
        }
        self.tabContentBottomConstraint = tabContentBottomConstraint
    

    I left the constraint as a weak reference even though it is no longer injected since the view itself will have a reference to it to keep it alive. It works.

    HOWEVER, I'm leaving the question open for a better solution. The above search is very fragile some the layout change in the future. It would be much better if the framework was injecting the constraint without breaking the layout. Still open for better solutions.