Autolayout Breakpoints

Long Vu
6 min readApr 6, 2020

--

Auto layout has become a crucial tool for iOS and OS X development. It makes creating layout for multiple screen sizes easy peasy. But sometimes it can drive you crazy, with verbose and misleading logs.

That’s a huge log! And I cut off the NSLayoutConstraint part. Yet, the second last line is giving a clue in which direction to go to fix this issue. Symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints.

All right, here’s what Xcode want’s you to do:

Honestly, that won’t help much, because basically it’ll just stop the execution and leave you up with LLDB, alone in the dark.

But there’s a little trick you can do to enhance the preceding symbolic breakpoint. Adding po [[UIWindow keyWindow] _autolayoutTrace] to it (for Obj-C projects) or expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace] (for Swift projects).

Now, on console, you’ll see all the UIView hierarchy and exactly where it has ambiguity.

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

Note that as you hit continue it’ll stop at every ambiguous layout you may have. And if that’s not enough for you to find out your autolayout issue, try changing the view’s color, who knows?

expr -l Swift -- import UIKit
expr -l Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.red

by Rafael Machado, 2015 Aug 17

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Long Vu
Long Vu

Written by Long Vu

Product builder, Engineering Manager, AI enthusiastic

No responses yet

Write a response