iosxcodeconstraintsuistoryboardsize-classes

Xcode Storyboard - Convert all of my constraints for a specific size class to the constraint for Any x Any


I ran into this issue a while back, when I pulled some storyboard updates from another computer via github.

What happens is every time I open up Xcode, it takes forever to load, and I end up with dozens, sometimes hundreds of misplaced views. This has been plaguing me for over a year, and I've literally just gone through each warning and set the frames to be what they expected to get rid of the warnings.

I've traced the error to be the use of Size classes. In hindsight, didn't really need 'em. We're only a portrait app, and have no intention of ever implementing a landscape feature. Definitely not any time soon.

The problem is that the storyboard loads in Any x Any, then switches to Compact x Regular, and a bunch of views are misplaced.

Here is the source code for one such misplaced view:

<imageView userInteractionEnabled="NO" alpha="0.0" contentMode="top" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" misplaced="YES" image="SmallGreySwipeCircle" translatesAutoresizingMaskIntoConstraints="NO" id="jEr-aS-2Yb" userLabel="previousIcon">
<rect key="frame" x="70" y="187" width="180" height="194"/>
<constraints>
        <constraint firstAttribute="width" constant="180" id="JSJ-EG-Mmh"/>
    <constraint firstAttribute="height" constant="194" id="TJx-aa-8Cn"/>
</constraints>
<variation key="default">
    <mask key="constraints">
                <exclude reference="JSJ-EG-Mmh"/>
                <exclude reference="TJx-aa-8Cn"/>
            </mask>
</variation>
    <variation key="heightClass=regular-widthClass=compact">
        <mask key="constraints">
                <include reference="JSJ-EG-Mmh"/>
                <include reference="TJx-aa-8Cn"/>
            </mask>
    </variation>
</imageView>

The piece to look at are the two <variation> blocks.

One is for the Any x Any, and the other is for regular compact.

How might I go about fixing this so that I keep all of the constraints that I have on my Regular x Compact size class, but make them all constraints for Any x Any?

I have too many to do this manually, and I'm not familiar with whatever language this is. XAML? Idk.

Looking at it, I want to guess that I could just change <exclude to <include.. Could anyone verify this before I break my storyboard?


Solution

  • OK, so here's what I found:

    Constraints are created for each item, regardless of sizeclass. However, there is a <include.....> and <exclude...> setting, and they only get included in the size class they were created in / checked on the Size Inspector.

    I tried just doing a find/replace for <exclude and setting it to <include.

    The problem with that is that it only includes all of the constraints.

    A tangential issue is that when you create an object and drag it into your view controller, it is only being added to that size class. You have to add it to all of the others. And this isn't as easy as swapping a '<include. Those are only added to the ViewController's implementation for each size class, so setting constraints to <include instead of <exclude ends up adding constraints for objects that don't exist in each size class.

    If your storyboard isn't too big, and you only use one size class (i.e. my app is only portrait mode, no landscape), a way to fix this is to go to each object's size inspector and make sure the Any size class is checked, and do the same for each constraint it has.

    If you use multiple size classes, I don't think there's a good way to resolve this bug without potentially introducing unintended behavior. May God have mercy on your soul.