BadmintonCat
BadmintonCat

Reputation: 9576

UIScrolView auto layout contraints breaking on device rotation

I'm having a rather annoying problem with auto-layout constraints set on a UIScrollView and its sub views. When the device orientation changes, it breaks a constraint with the following warning:

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) 
(
    "<NSLayoutConstraint:0x7a1b1830 V:[UIView:0x7a1b0520(768)]>",
    "<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>",
    "<NSLayoutConstraint:0x7a17aa70 V:|-(0)-[UIView:0x7a1b0520]   (Names: '|':UIScrollView:0x7a176520 )>",
    "<NSLayoutConstraint:0x7a1c49c0 V:[UIView:0x7a1b0520]-(0)-|   (Names: '|':UIScrollView:0x7a176520 )>",
    "<NSLayoutConstraint:0x7a172620 V:[UIView:0x7a1bcf50]-(0)-|   (Names: '|':UIScrollView:0x7a176520 )>",
    "<NSLayoutConstraint:0x7a172650 V:|-(0)-[UIView:0x7a1bcf50]   (Names: '|':UIScrollView:0x7a176520 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>

I've set up a scroll view in my storyboard and it contains two containers as sub views. The scroll view itself is pinned on all four sides to the superview (Editor/Pin/Leading-, Trailing-, Top-, Bottom-Space to superview). The two containers have their edges pinned to the scroll view with Auto-Layout constraints but the width & height of both is set as fixed on the storyboard, see att. image:

enter image description here

The width and height of the two containers gets updated via code, once initially in viewDidLoad() and whenever the devices orientation changes, in didRotateFromInterfaceOrientation():

    _primaryWidth.constant = view.bounds.size.width
    _primaryHeight.constant = view.bounds.size.height
    _secondaryWidth.constant = _primaryWidth.constant - 200
    _secondaryHeight.constant = _primaryHeight.constant

This is when the above warning appears and the constraints break and the layout goes overboard. Can somebody tell me why this is happening and how to fix it?

(Note the minus 200. This is because the right container should have a smaller width. But it doesn't affect the issue. The constraints break even without this.)

Upvotes: 0

Views: 1923

Answers (1)

DBD
DBD

Reputation: 23233

You have constraints which pin the edges of the scroll view to the edges of the screen which works in both portrait and landscape.You also have a constraint which sets the height of one of your views to 1024.

In portrait that all works, but the moment you rotate to landscape you can't have something be 1024 height pinned to the edge of the screen on top an bottom because the screen is only 768 in height. One has to go and you can see which one gets the axe.

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>

Remove the height constraints and you'll be fine. Why would you need them anyway? You want the views to pin to the edge of the screen/superview regardless of the size your given. Non-arbitrary values will also allow you to carry the same code/layout to other devices or as sub-views without layout changes.

Upvotes: 2

Related Questions