ishahak ishahak - 1 month ago 6
iOS Question

iOS "Unable to simultaneously satisfy constraints"

I will use the following notation to explain the invovled views:


  • {V} – the ‘superview’, i.e. the main view of the root controller

  • {Q} – a rectangle at the center of the screen used as a quiz

  • {W} – a white bar above {Q}



I’m getting the following output when running on iPad-Air2 simulator:

2016-11-03 08:09:07.700117 MyApp[16645:6976134] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x60000009d600 h=--& v=--& QuizButtons:0x7fcb8e521830.width == 717 (active)>",
"<NSLayoutConstraint:0x608000281fe0 H:|-(0)-[ImgWhiteBar:0x7fcb8e525020] (active, names: '|':ViewTestVC:0x7fcb8e639b30 )>",
"<NSLayoutConstraint:0x6080002820d0 H:[ImgWhiteBar:0x7fcb8e525020]-(0)-| (active, names: '|':ViewTestVC:0x7fcb8e639b30 )>",
"<NSLayoutConstraint:0x608000282210 ImgWhiteBar:0x7fcb8e525020.width == 1.07143*QuizButtons:0x7fcb8e521830.width (active)>",
"<NSLayoutConstraint:0x60000009b9e0 'UIView-Encapsulated-Layout-Width' ViewTestVC:0x7fcb8e639b30.width == 768 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6080002820d0 H:[ImgWhiteBar:0x7fcb8e525020]-(0)-| (active, names: '|':ViewTestVC:0x7fcb8e639b30 )>

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.


My interpretation to logged constraints is this:


  1. {Q}: default
    <h=--& v=--&>
    , width =717

  2. Horiz: {V.lead} -0- {W}

  3. Horiz: {W} -0- {V.trail}

  4. {W.width} = 1.07 * {Q.width}

  5. {V.width} = 768



Or maybe a bit simpler


  1. {Q.width} must be 717

  2. {W.width} must be 768.21531

  3. {W} must touch both sides of {V}

  4. {V.width} = 768



Questions:


  • Is my interpretation correct?

  • What is the problem here? It is due to the inaccuracy of the 768.2 vs 768? If yes, who told Xcode to use 717? I told {Q.width} to be {W.width}/[14:15]



Will appreciate any help here!

EDIT

Here are three of the constraints:

enter image description here
enter image description here
enter image description here

Answer

The list of the conflicting constraints includes h=--& v=--& which is the default non-autolayout form.

I was trying to get the initial size and position using auto-layout, and then tried to turn auto-layout off by setting translatesAutoresizingMaskIntoConstraints=YES. I got an answer in the Apple developer forum saying that in such case I need to remove all constraints for the view, possibly by removing from the superview and adding back.

TIP

While investigating this bug, I have found a way to make the constraints-conflict log much easier to understand. The problem is that the views appear anonymous, specifying only the class but not the name.

To make your views identifiable, open one of your .m files and add a new class for each view you want to identify, like this:

@interface ImgWhiteBar: UIImageView
@end
@implementation ImgWhiteBar
@end    

@interface Spacer1: UIView
@end
@implementation Spacer1
@end

After that, in InterfaceBuilder, select each view, and then at the "Identity Inspector" on the right modify the generic class (UIVIew, UIImageView etc.) into one of the classes you just created.

Now run again, and Abracadabra - all views are now identified with their custom classes, allowing you to understand what is going on there.

Have fun debugging constraints!