In the Auto Layout and Size Class video series, we came up with a generic layout. We made a different layout for iPhones in landscape and then another for iPads. However the preview in iPhone 6 plus in landscape is not working.
In the last video we solved the problem quickly. In this post I’d like to go into more detail about conflicting constraints. Our goal will be to have a landscape view like an iPad and a portrait like an iPhone.
This lesson assumes you have built a few class sizes first. You can follow along with the videos. For those who wish to follow along and not do all that work, I have a Zip file you can download here.
The iPhone 6 plus is an odd device. It acts like a iPhone in portrait and an iPad in landscape. iPhone 6 has a compact width in portrait like a phone and a regular width in landscape like a tablet.
In the videos, we have built sets of constraints for wAny hAny, wAny hCompact and wRegular hAny. The iPhone 6 plus landscape is wRegular,hCompact. The phone inherits constraints from both wAny hCompact and wRegular hAny. These constraints between the two sets are not the same, creating conflicting constraints. This makes most of our UI disappear, since Xcode can’t figure out what to do
If you do not already have the project open, open the project. Change the size class of the storyboard to regular width, compact height to get the class size storyboard for the iPhone 6 plus landscape:
The screen is full of errors:
Select the text view button from the outline and the size inspector shows all the constraints:
We have a lot of duplicate entries. Select the Pepperoni button from the outline and you will see many constraints, so many they don’t fit on the screen. Open the error pane by clicking the small red circle on the document outline and you will see all those problems.
There are several strategies to deal with this mess. The most important one is to plan ahead. One simple change would have prevented this. I could have done the iPhone landscape in wCompact,hCompact. It would only apply to the smaller phones in landscape and ignore the iPhone 6 plus. The wRegular,hAny would have set the landscape for the iPhone 6 plus to the same as the iPad.
However, no one can plan ahead for everything. Someone in your organization might add a new feature to one layout that messes up everything. You might change your mind on a UI feature halfway through implementation. It happens. We need to know how to fix conflicting constraints.
There are two ways to solve constraint errors: Delete all the constraints of a view then start over or delete only the conflicting constraints.
Deleting Conflicting Constraints
For our example, we want the regular width constraints to remain and the compact width constraints to disappear, leaving us with the appearance we get on the iPad.
You can delete constraints in the error panel, but I find it does not give me enough information about what I am deleting. Go back to the document outline and select the Cheese button. In the size inspector, you will find these constraints among others:
The Equal Widths and Equal Heights have duplicates. Duplicates are not conflicting, but they are messy. Click on the left side of one of the Equal Width duplicates and press Delete on your keyboard. Do the same for the Equal Height duplicate. That’s the easy stuff. Above these you will find the serious conflicts.
Refer to your previous layout to know what to delete. For example we have two leading space constraints: Leading Space to Superview and Leading Space to Pepperoni Equals 10. We want the regular width,which was 10 points from Pepperoni. Delete the Leading Space to Superview. Similarly we want to align to the top of Pepperoni. We have a choice between Align Top to Pepperoni and Top Space to Pepperoni Equals 10 points. Delete the unwanted Top Space to Pepperoni Equals 10 points. When done, it should look like this:
Deleting Conflicting Constraints: The Pepperoni Button
This won’t change anything because the Cheese button is dependent for its size information on the Pepperoni button, which is so messed up it has no size information. Fix that next. Select Pepperoni in the document outline. You get that long list of constraints. Start with the easy duplicates. You will find this in the size inspector:
Delete one of these duplicates. Going through the list another conflict is the width:
On the regular width version of the layout, we have a proportionally sized button. Delete the Equal Width to Done. With that change, we start to see views in the preview,though not sized right:
There is only one more conflict. Does the Pepperoni button’s trailing space go to the Cheese button or the text view?
These are the in-line buttons, so it goes to Cheese. Delete Trailing Space to: Text View Equals 10.
The Done Button
Click on the black background of the superview. In the resolver, click the Update Frames in the All Views in View controller section. We get our views back, though not quite right yet. Click the done button and you can see it still has conflicts:
The Done button is to blame for the buttons stretching down the view. In the iPhone landscape it was anchored to the bottom of the superview. Delete this constraint:
Update all frames and you get buttons again, though not quite what we wanted:
Clearing all Constraints of a View
Often, it is just easier to clear all constraints for a view and start over.
Shift-select the Done button and the text view. In the resolver select the Clear Constraints in the Selected Views part. Resize the text view like this:
By resizing, the text view has a nearest neighbor on top of the buttons, and the left,right and bottom margins on the other three sides. We can pin the text view in one step. Pin the text view like this:
Add some constraints to the Done button. Control-drag from Done to Pepperoni. Shift-click Top, Equal Widths and Equal Heights, then press Return.
Pin the Done button like this to put constraint to Cheese and the Right Margin.:
With the Done button selected, edit the Equal Width to Pepperoni by changing the multiplier to 1:3. If the Done button gets bigger than the other buttons, make the multiplier 3.
Everything is set up correctly. On the resolve menu, click Update Frames in the All Frames section.
Going over to the preview pane, we see the iPhone 6 plus is now set up correctly.
We’ve now completed the size class and auto layout of this app’s storyboard by getting rid of all the errors.
Some Tips for Class Sizes and Layout
It best to avoid errors. Some planning and knowledge helps a lot to prevent errors. Here’s a few tips to help you using auto layout with Size classes:
- Plan Ahead with Mockups: Have on paper exactly what you want for all the devices you will lay out for.
- Avoid Any Width, Compact Height: For most layout you will want what we did in this chapter. The iphone 6 plus will act like an iPhone in portrait and an ipad in landscape. TO avoid the errors we corrected in this section use wCompact hCompact for the iPhone landscape layout.
- Think iPad for wAnyhAny, get specific for iPhone: For the generic case start with your layout for iPad. Like above, it avoids conflicts. Make a different wCompact hRegular for iPhone Portrait.