269

I'm seeing an error appear in my debugger log:

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

How do I trap on that call? It does not appear anywhere in my code.

Screenshot1

Jayprakash Dubey
  • 32,447
  • 16
  • 161
  • 169
Maury Markowitz
  • 8,303
  • 8
  • 36
  • 79
  • In 9 out of 10 cases: this is just caused by: for some view or item on yoru storyboard, you uncheck "Installed". (For example, just a development button or something you didn't need any more.) In general, it handles "not-Installed" badly: it often leaves constraints there which become meaningless without the not-Installed item. Often the solution is simply to delete items you have forgotten about, that are sitting around "not-Installed" - just delete 'em. – Fattie Apr 10 '17 at 10:30

5 Answers5

502

This post helped me A LOT!

I added UIViewAlertForUnsatisfiableConstraints symbolic breakpoint with suggested action:

Obj-C project

po [[UIWindow keyWindow] _autolayoutTrace]

Symbolic breakpoint with custom action in Objective-C project

Swift project

expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]

Symbolic breakpoint with custom action

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 Pause 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!

Hinted View

Simply amazing! Hope It helps.

thefabbulus
  • 2,080
  • 2
  • 24
  • 47
Thomás Pereira
  • 8,869
  • 2
  • 28
  • 34
  • @TomCalmon Where did u fire this command to change background color of your view?? – iAnurag Jul 12 '17 at 11:02
  • 4
    @iAnurag You can run commands in console area, when execution is paused. – Thomás Pereira Jul 12 '17 at 14:18
  • 2
    @TomCalmon I did the same...but it shows following error `rror: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x7f88a8cc2050). The process has been returned to the state before expression evaluation.` – iAnurag Jul 13 '17 at 07:10
  • 1
    It's happening to me the same :/ After all the steps, I write in console: `expr -l Swift -- import UIKit expr -l Swift -- unsafeBitCast(0x102083e00, to: UITableView.self).backgroundColor = UIColor.red` and I get the same error: `error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x5214c1438). The process has been returned to the state before expression evaluation.` @iAnurag could you find a solution? – celiux Aug 28 '17 at 09:57
  • I get `error: use of undeclared identifier 'expr'` & `error: use of undeclared identifier 'l'` – Honey Nov 14 '17 at 15:35
  • @iAnurag this could happen if the view with address=0x7f88a8cc2050 has been already deallocated and not in memory anymore. – Sapozhnik Ivan Jan 23 '18 at 15:36
  • 4
    `expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]` returns `nil` for me – Igor Andreev Apr 06 '18 at 12:29
  • 2
    Make sure you replace 0x7f88a8cc2050 with the memory address of your object and run the command in the console when execution pauses. – Tom Howard Jul 19 '18 at 14:36
  • 2
    Still working in Swift 4 and Xcode 9.4, thanks a lot! – atereshkov Aug 13 '18 at 11:39
  • 3
    Unfreakingbelievable. Great tip here, totally helped me go straight to the issue. Once the item is changed to red, continue the execution if possible and you'll see the highlight. – Aaron Sep 15 '18 at 22:02
  • 1
    `expr (void)[CATransaction flush]` after changing color – Isaak Osipovich Dunayevsky Nov 09 '18 at 13:42
  • 1
    Amazing tip! Thanks a million for this!! – user1898712 Jan 17 '19 at 17:09
  • I also had to check "Automatically continue after evaluating actions" otherwise nothing was dumped into the console. – Todd Oct 14 '19 at 13:09
  • 2
    @TomHoward any ideas why I don't see any clues in the output: `AMBIGUOUS LAYOUT`, `MISSING HOST CONSTRAINTS`, etc? – SoftDesigner Oct 25 '19 at 10:51
  • NSURLConnection finished with error - code -1001 Stopped due to an error evaluating condition of breakpoint 1.1: "expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]" Couldn't parse conditional expression: error: use of undeclared identifier 'expr' error: use of undeclared identifier 'l' – Marlhex Nov 08 '19 at 20:45
  • 1
    How to find the problematic view? I have 30 views... and where to add this line -> Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.red Is there a YouTube video for this ? – Bogdan Bogdanov Feb 12 '20 at 01:37
  • 4
    When trying this I'm getting `error: Execution was interrupted, reason: internal ObjC exception breakpoint(-5)..` – mag_zbc May 28 '20 at 11:38
  • Sometimes I get this error when hitting the breakpoint: `2021-03-24 15:41:42.141413+0100 NB[29965:5238269] *** Assertion failure in -[NSISEngine _optimizeWithoutRebuilding], NSISEngine.m:1639 error: Execution was interrupted, reason: internal ObjC exception breakpoint(-5).. The process has been returned to the state before expression evaluation.` – piotr_ch Mar 24 '21 at 14:43
267

You'll want to add a Symbolic Breakpoint. Apple provides an excellent guide on how to do this.

  1. Open the Breakpoint Navigator cmd+7 (cmd+8 in Xcode 9)
  2. Click the Add button in the lower left
  3. Select Add Symbolic Breakpoint...
  4. Where it says Symbol just type in UIViewAlertForUnsatisfiableConstraints

You can also treat it like any other breakpoint, turning it on and off, adding actions, or log messages.

Stephen Furlani
  • 6,586
  • 4
  • 27
  • 56
  • 59
    I just don't understand how I can debug the problem better with this hint. I added a symbolic breakpoint but it still doesn't give me enough information whats the problem. The only way is trying to read line by line and understand what causes the problem....otherwise clearing the constraints and again adding them together with the Preview in the asisstent view should help most! – Alex Cio Mar 13 '15 at 12:26
  • 11
    This might help to get more info after stopping at the breakpoint: http://staxmanade.com/2015/06/debugging-ios-autolayout-issues/ – fabb Jul 24 '15 at 09:22
  • 1
    Just adding that you can now give identifiers to the constraints directly in IB so when you're debugging them, that's the name you'll see. – Mark A. Donohoe Oct 14 '16 at 21:51
  • 2
    (follow-up on @MarqueIV ) `NSLayoutConstraint` has had an `identifier` property since iOS **7** — _Xcode 7 and above_, which can be set both from IB Storyboards as well from code. By setting the identifier you can easier distinguish between system-generated and user-generated constraints in the debug log, e.g. `myConstraint.identifier = "centered image"` (source & examples: http://useyourloaf.com/blog/using-identifiers-to-debug-autolayout/) – PDK Dec 13 '16 at 14:35
  • @AlexCio How it helps? The least it does is it pauses at the moment that it happens. It gives a stack trace where you can backtrack and find the origin... – Honey Dec 06 '18 at 18:20
  • @Honey the debug message printed in 2015 was not helpful at all. They've gotten better over the years, and there are better ways of debugging now that allow you to label identifiers with constraints – Stephen Furlani Dec 08 '18 at 21:54
  • It will help you if you have one main view compose from 2-3 child views, you will know where you need to fix the constrains. – zdravko zdravkin Apr 16 '20 at 12:39
11

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.

Sategroup
  • 907
  • 13
  • 27
  • 3
    The compiler? You mean the runtime? The compiler didn't remove the constraint. The compiler left it there for the runtime to deal with, hence "recover by breaking constraint" *during runtime*. – drhr Jul 30 '15 at 16:16
2

Whenever I attempt to remove the constraints that the system had to break, my constraints are no longer enough to satisfy the IB (ie "missing constraints" shows in the IB, which means they're incomplete and won't be used). I actually got around this by setting the constraint it wants to break to low priority, which (and this is an assumption) allows the system to break the constraint gracefully. It's probably not the best solution, but it solved my problem and the resulting constraints worked perfectly.

Nick Molyneux
  • 359
  • 1
  • 2
  • 19
  • 2
    Typically that is a situation where you want to use a placeholder constraint which is removed at runtime. To make a constraint a placeholder constraint, go to the constraint inspector and click "Remove at build time". Notice how the constraint I-beam symbol in the IB drawing area turns from blue to grey to indicate this. – spencery2 Dec 31 '15 at 23:49
  • 1
    I had the same issue. when i remove the broken constraint my design broke. So i set the priority to medium. – Jeremy Piednoel Sep 26 '16 at 14:02
0

This usually appears when you want to use UIActivityViewController in iPad.

Add below, before you present the controller to mark the arrow.

activityViewController.popoverPresentationController?.sourceRect = senderView.frame // senderView can be your button/view you tapped to call this VC

I assume you already have below, if not, add together:

activityViewController.popoverPresentationController?.sourceView = self.view

Umit Kaya
  • 4,719
  • 2
  • 34
  • 46