How to trap on UIViewAlertForUnsatisfiableConstraints?
Followed Stephen's advice and tried to debug the code and whoa! it worked. The answer lies in the debug message itself.
Will attempt to recover by breaking constraint
NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>
The line above tells you that the runtime worked by removing this constraint. May be you don't need Horizontal Spacing on your button (MPKnockoutButton). Once you clear this constraint, it won't complain at runtime & you would get the desired behaviour.
You'll want to add a Symbolic Breakpoint
. Apple provides an excellent guide on how to do this.
- Open the Breakpoint Navigator
cmd+7
(cmd+8
in Xcode 9) - Click the
Add
button in the lower left - Select
Add Symbolic Breakpoint...
- Where it says
Symbol
just type inUIViewAlertForUnsatisfiableConstraints
You can also treat it like any other breakpoint, turning it on and off, adding actions, or log messages.
This post helped me A LOT!
I added UIViewAlertForUnsatisfiableConstraints symbolic breakpoint with suggested action:
Obj-C project
po [[UIWindow keyWindow] _autolayoutTrace]
Swift project
expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]
With this hint, the log became more detailed, and It was easier for me identify which view had the constraint broken.
UIWindow:0x7f88a8e4a4a0
| UILayoutContainerView:0x7f88a8f23b70
| | UINavigationTransitionView:0x7f88a8ca1970
| | | UIViewControllerWrapperView:0x7f88a8f2aab0
| | | | •UIView:0x7f88a8ca2880
| | | | | *UIView:0x7f88a8ca2a10
| | | | | | *UIButton:0x7f88a8c98820'Archived'
| | | | | | | UIButtonLabel:0x7f88a8cb0e30'Archived'
| | | | | | *UIButton:0x7f88a8ca22d0'Download'
| | | | | | | UIButtonLabel:0x7f88a8cb04e0'Download'
| | | | | | *UIButton:0x7f88a8ca1580'Deleted'
| | | | | | | UIButtonLabel:0x7f88a8caf100'Deleted'
| | | | | *UIView:0x7f88a8ca33e0
| | | | | *_UILayoutGuide:0x7f88a8ca35b0
| | | | | *_UILayoutGuide:0x7f88a8ca4090
| | | | | _UIPageViewControllerContentView:0x7f88a8f1a390
| | | | | | _UIQueuingScrollView:0x7f88aa031c00
| | | | | | | UIView:0x7f88a8f38070
| | | | | | | UIView:0x7f88a8f381e0
| | | | | | | | •UIView:0x7f88a8f39fa0, MISSING HOST CONSTRAINTS
| | | | | | | | | *UIButton:0x7f88a8cb9bf0'Retrieve data'- AMBIGUOUS LAYOUT for UIButton:0x7f88a8cb9bf0'Retrieve data'.minX{id: 170}, UIButton:0x7f88a8cb9bf0'Retrieve data'.minY{id: 171}
| | | | | | | | | *UIImageView:0x7f88a8f3ad80- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8f3ad80.minX{id: 172}, UIImageView:0x7f88a8f3ad80.minY{id: 173}
| | | | | | | | | *App.RecordInfoView:0x7f88a8cbe530- AMBIGUOUS LAYOUT for App.RecordInfoView:0x7f88a8cbe530.minX{id: 174}, App.RecordInfoView:0x7f88a8cbe530.minY{id: 175}, App.RecordInfoView:0x7f88a8cbe530.Width{id: 176}, App.RecordInfoView:0x7f88a8cbe530.Height{id: 177}
| | | | | | | | | | +UIView:0x7f88a8cc1d30- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1d30.minX{id: 178}, UIView:0x7f88a8cc1d30.minY{id: 179}, UIView:0x7f88a8cc1d30.Width{id: 180}, UIView:0x7f88a8cc1d30.Height{id: 181}
| | | | | | | | | | | *UIView:0x7f88a8cc1ec0- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1ec0.minX{id: 153}, UIView:0x7f88a8cc1ec0.minY{id: 151}, UIView:0x7f88a8cc1ec0.Width{id: 154}, UIView:0x7f88a8cc1ec0.Height{id: 165}
| | | | | | | | | | | | *UIView:0x7f88a8e68e10- AMBIGUOUS LAYOUT for UIView:0x7f88a8e68e10.minX{id: 155}, UIView:0x7f88a8e68e10.minY{id: 150}, UIView:0x7f88a8e68e10.Width{id: 156}
| | | | | | | | | | | | *UIImageView:0x7f88a8e65de0- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e65de0.minX{id: 159}, UIImageView:0x7f88a8e65de0.minY{id: 182}
| | | | | | | | | | | | *UILabel:0x7f88a8e69080'8-6-2015'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8e69080'8-6-2015'.minX{id: 183}, UILabel:0x7f88a8e69080'8-6-2015'.minY{id: 184}, UILabel:0x7f88a8e69080'8-6-2015'.Width{id: 185}
| | | | | | | | | | | | *UILabel:0x7f88a8cc0690'16:34'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8cc0690'16:34'.minX{id: 186}, UILabel:0x7f88a8cc0690'16:34'.minY{id: 187}, UILabel:0x7f88a8cc0690'16:34'.Width{id: 188}, UILabel:0x7f88a8cc0690'16:34'.Height{id: 189}
| | | | | | | | | | | | *UIView:0x7f88a8cc2050- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc2050.minX{id: 161}, UIView:0x7f88a8cc2050.minY{id: 166}, UIView:0x7f88a8cc2050.Width{id: 163}
| | | | | | | | | | | | *UIImageView:0x7f88a8e69d90- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e69d90.minX{id: 190}, UIImageView:0x7f88a8e69d90.minY{id: 191}, UIImageView:0x7f88a8e69d90.Width{id: 192}, UIImageView:0x7f88a8e69d90.Height{id: 193}
| | | | | | | | | | | *UIView:0x7f88a8f3cc00
| | | | | | | | | | | | *UIView:0x7f88a8e618d0
| | | | | | | | | | | | *UIImageView:0x7f88a8e5ba10
| | | | | | | | | | | | *UIView:0x7f88a8f3cd70
| | | | | | | | | | | | *UIImageView:0x7f88a8e58e10
| | | | | | | | | | | | *UIImageView:0x7f88a8e5e7a0
| | | | | | | | | | | | *UIView:0x7f88a8f3cee0
| | | | | | | | | | | *UIView:0x7f88a8f3dc70
| | | | | | | | | | | | *UIView:0x7f88a8e64dd0
| | | | | | | | | | | | *UILabel:0x7f88a8e65290'Average flow rate'
| | | | | | | | | | | | *UILabel:0x7f88a8e712d0'177.0 ml/s'
| | | | | | | | | | | | *UILabel:0x7f88a8c97150'1299.4'
| | | | | | | | | | | | *UIView:0x7f88a8f3dde0
| | | | | | | | | | | | *UILabel:0x7f88a8f3df50'Maximum flow rate'
| | | | | | | | | | | | *UILabel:0x7f88a8cbfdb0'371.6 ml/s'
| | | | | | | | | | | | *UILabel:0x7f88a8cc0230'873.5'
| | | | | | | | | | | | *UIView:0x7f88a8f3e2a0
| | | | | | | | | | | | *UILabel:0x7f88a8f3e410'Total volume'
| | | | | | | | | | | | *UILabel:0x7f88a8cc0f20'371.6 ml'
| | | | | | | | | | | | *UIView:0x7f88a8f3e870
| | | | | | | | | | | | *UILabel:0x7f88a8f3ea00'Time do max. flow'
| | | | | | | | | | | | *UILabel:0x7f88a8cc0ac0'3.6 s'
| | | | | | | | | | | | *UIView:0x7f88a8f3ee10
| | | | | | | | | | | | *UILabel:0x7f88a8f3efa0'Flow time'
| | | | | | | | | | | | *UILabel:0x7f88a8cbf980'2.1 s'
| | | | | | | | | | | | *UIView:0x7f88a8f3f3e0
| | | | | | | | | | | | *UILabel:0x7f88a8f3f570'Voiding time'
| | | | | | | | | | | | *UILabel:0x7f88a8cc17e0'3.5 s'
| | | | | | | | | | | | *UIView:0x7f88a8f3f9a0
| | | | | | | | | | | | *UILabel:0x7f88a8f3fb30'Voiding delay'
| | | | | | | | | | | | *UILabel:0x7f88a8cc1380'1.0 s'
| | | | | | | | | | | | *UIView:0x7f88a8e65000
| | | | | | | | | | | | *UIButton:0x7f88a8e52f20'Show'
| | | | | | | | | | | | *UIImageView:0x7f88a8e6e1d0
| | | | | | | | | | | | *UIButton:0x7f88a8e52c90'Send'
| | | | | | | | | | | | *UIImageView:0x7f88a8e61bb0
| | | | | | | | | | | | *UIButton:0x7f88a8e528e0'Delete'
| | | | | | | | | | | | *UIImageView:0x7f88a8e6b3f0
| | | | | | | | | | | | *UIView:0x7f88a8f3ff60
| | | | | | | | | *UIActivityIndicatorView:0x7f88a8cba080
| | | | | | | | | | UIImageView:0x7f88a8cba700
| | | | | | | | | *_UILayoutGuide:0x7f88a8cc3150
| | | | | | | | | *_UILayoutGuide:0x7f88a8cc3b10
| | | | | | | UIView:0x7f88a8f339c0
| | UINavigationBar:0x7f88a8c96810
| | | _UINavigationBarBackground:0x7f88a8e45c00
| | | | UIImageView:0x7f88a8e46410
| | | UINavigationItemView:0x7f88a8c97520'App'
| | | | UILabel:0x7f88a8c97cc0'App'
| | | UINavigationButton:0x7f88a8e3e850
| | | | UIImageView:0x7f88a8e445b0
| | | _UINavigationBarBackIndicatorView:0x7f88a8f2b530
Legend:
* - is laid out with auto layout
+ - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
• - layout engine host
Then I paused execution and I changed problematic view's background color with the command (replacing 0x7f88a8cc2050
with the memory address of your object of course)...
Obj-C
expr ((UIView *)0x7f88a8cc2050).backgroundColor = [UIColor redColor]
Swift 3.0
expr -l Swift -- import UIKit
expr -l Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.red
... and the result It was awesome!
Simply amazing!