NSTableView conflicting constraints based on internal autosizing flags

In macOS 10.12, my app's NSTableView in "source list" mode causes an unsatisfied constraints error that doesn't occur in 10.11. This occurs even when running a 10.11 based version of the app on 10.12. My hunch is it has to do with changes to the Layout Pass as described in AppKit release notes: https://developer.apple.com/library/prerelease/content/releasenotes/AppKit/RN-AppKit/index.html


It might be a pure frameworks bug, but I'd like to take a look at the conflicting constraints to make sure I'm not involved somehow. Unfortunately the log in the console says:


2016-06-21 00:30:50.300109 MarsEdit[33315:1741227] [Layout] Unable to simultaneously satisfy constraints:

<private>

Will attempt to recover by breaking constraint

<private>


I can dig into this some more but I thought I'd post here to see if anybody had ideas about what the "<private>" indicates in this circumstance. Perhaps these are some magical, internal pseudo-constraints that I'm not supposed to ever see?

I'm actually seeing that <private> nomenclature for other things that should be logged. E.g. when AppKit was trying to log about an NSTableView delegate not implementing the expected methods. Something else is going on there, I think.

I think I'm probably running into an edge case with NSTable/OutlineView ... the bug only occurs when I have enough items in the table view to case a vertical scroller to appear, and if I have the system setting to "Always" show scrollers. So I suspect the scenario where a vertical scroller is not an overlay but an actual screen-space-occupying subview was not completely considered.

The <private> thing is likely an artifact of the new logging system introduced in iOS 10 and Sierra. By default, when not annotated, certain types (including arrays and strings) are redacted for privacy reasons. The autolayout API that's spitting out that error is likely not annotated properly.


Search for "Privacy" here: https://developer.apple.com/reference/os/1891852-logging?language=objc

It sounds like you've found a different issue than the one I did, but just in case it's helpful, I discovered when I loaded a XIB from 10.11 and saved it under Xcode 8, the constraints that were auto-created were changed in a way that broke my code.


The new system is a lot smarter, but it is incompatible with certain assumptions.

Basically, what happened is a view that was unconstrained (insdie a scrollview) before automatically got a size constraint at compile time, from its native size. I had been adding more constraints to this view at run time, but under Xcode 8 those new constraints weren't working because there was already the automatic size constraint from IB. So what I was seeing was it MOSTLY worked, until my view needed to be bigger than the size it happened to be in IB, then it failed.


The fix was super-simple — in IB I added constraints for x, y, height, width, and then marked them all as "remove as compile time" in IB. Boom everything worked again.


-W

Thanks, Wil! Yeah, I think I'm on to something different, because the same failure occurs with an app that was built before Xcode 8 was released. Sounds like there are going to be some bumps in the road, but hopefully not too many. Glad you found the solution for yours.

Following up on this a bit more, it seems like the constraint conflicts are (no surprise!) based on an NSAutoresizingMaskLayoutConstraint being created within NSTableView's infrastructure (relating my table cell view to the table row view). In the normal, non conflicting case, the constraint relates their bottom edges by 3 points, but int the broken case, it's by 40 points. I'm not sure yet what the cause is for this dramatic disparity.


I'm also not sure how seriously to take this. It's "just" a quiet logged conflict for end-users, but since I leave that debugging flag on all the time while working, I see the window turn purple often 🙂 In any case it never happened before 10.12.

If anybody else runs into this and is curious to compare notes: this is the list of conflicting constraints that I get. I've noticed that the conflict is also happening while the table row view is at index "-1", which may explain why metrics are in flux. It's the preparation phase for a new table row view being added to the view:


<__NSArrayM 0x10b3fb5e0>(

<NSAutoresizingMaskLayoutConstraint:0x10b3f6c80 h=--& v=-&- SourceListHeader.minY == + 4 (active, names: SourceListHeader:0x10b3d4950, '|':NSTableRowView:0x10b3aeb50 )>,

<NSAutoresizingMaskLayoutConstraint:0x10b3f6aa0 h=--& v=-&- V:[SourceListHeader]-(35)-| (active, names: SourceListHeader:0x10b3d4950, '|':NSTableRowView:0x10b3aeb50 )>,

<NSLayoutConstraint:0x10b3f76c0 'NSView-Encapsulated-Layout-Height' NSTableRowView:0x10b3aeb50.height == + 23 (active)>

)

NSTableView conflicting constraints based on internal autosizing flags
 
 
Q