Aleksander
Aleksander

Reputation: 2815

Why does autolayout have issues with this layout

I'm having some issues with Autolayout width on all screen sizes for a keyboard extension.

At first it worked fine, but then suddenly started spitting out a number of errors regardless of the width of the screen. I didn't change anything, I even tried deleting the app, cleaning the project, and laying out everything from scratch.

This is my layout:

| - 8 - (50) - >=8 - (130) - 8 - (130) - 8 - |
priority (50) = 750, everything else = 1000

Screenshot of storyboard layout

This is somehow causing a problem on not only the 320 point wide 4 inch screen, but also the 375 point wide 4.7 inch screen and 414 point wide 5.5 inch screen.

As far as I see, there shouldn't be any problems as the max width of the items is (8+50+8+130+8+130+8) 342 points. This is less than both the 4.7 and 5.5 inch screens. On the 4 inch, I solve this by breaking the 50 point width on button 1, so the total is 320 points.

It looks fine on both the simulator and device, however the console spits out a number of Unable to simultaneously satisfy constraints errors (3 to be exact).

Here's the log:

1: (
"<NSLayoutConstraint:0x1740954a0 H:[UIButton:0x137e0cb80'Last sentence'(130)]>",
"<NSLayoutConstraint:0x1740955e0 H:[UIButton:0x137e0cda0'Pasteboard'(130)]>",
"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>",
"<NSLayoutConstraint:0x174095950 H:[UIButton:0x137e0cda0'Pasteboard']-(8)-[UIButton:0x137e0cb80'Last sentence']>",
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(55)]>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x1740955e0 H:[UIButton:0x137e0cda0'Pasteboard'(130)]>

2: (
"<NSLayoutConstraint:0x1740954a0 H:[UIButton:0x137e0cb80'Last sentence'(130)]>",
"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>",
"<NSLayoutConstraint:0x174095950 H:[UIButton:0x137e0cda0'Pasteboard']-(8)-[UIButton:0x137e0cb80'Last sentence']>",
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(55)]>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x1740954a0 H:[UIButton:0x137e0cb80'Last sentence'(130)]>

3: (
"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>",
"<NSLayoutConstraint:0x174095950 H:[UIButton:0x137e0cda0'Pasteboard']-(8)-[UIButton:0x137e0cb80'Last sentence']>",
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(0)]>"
)
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x1740958b0 H:[UIButton:0x137d0ba60]-(>=8)-[UIButton:0x137e0cda0'Pasteboard']>

I've been scratching my head with this all evening. Do you guys have any suggestions?

Upvotes: 2

Views: 156

Answers (2)

Ken Thomases
Ken Thomases

Reputation: 90671

For whatever reason, the superview is, at least temporarily, only 55 points wide. From the log you quoted:

"<NSLayoutConstraint:0x174095810 H:|-(8)-[UIButton:0x137d0ba60]   (Names: '|':UIView:0x137e0c1b0 )>",
...
"<NSLayoutConstraint:0x1740959f0 H:[UIButton:0x137e0cb80'Last sentence']-(8)-|   (Names: '|':UIView:0x137e0c1b0 )>",
"<NSLayoutConstraint:0x170094ff0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x137e0c1b0(55)]>"

So, | (the superview's edges) is UIView:0x137e0c1b0 and that's constrained to 55 points wide (UIView:0x137e0c1b0(55)).

That view is presumably controlled by the frameworks. You need to accommodate it having any arbitrary width (even 0, as in the last exception). To do that, make one of the horizontal spacing constraints very high, but not required, priority, such as 950. That way, it will hold if it possibly can, but be broken without causing an exception if it has to be. The obvious choice is the constraint to the superview's trailing edge.

The cases where the superview is narrower than the screen are presumably when the view hierarchy is being put together, before it's shown. So, allowing the constraint to be broken at that time won't affect any actually-visible layout.

Upvotes: 2

Oxcug
Oxcug

Reputation: 6604

If I'm not mistaken... It looks like you have constant width & margin constraints on your "Pasteboard" and "Last Scentence" button.

You're constraints to the side of the screen are already declaring the width. So when auto layout runs, it (understandably) doesn't know which constraint to use. So it breaks the width constraints on both your buttons and uses the other margin constraints to set the width.

Upvotes: 1

Related Questions