Adaptive Design
Understanding the big ideas.
A quick note — all of my future posts will be published on my dedicated website and this publication is no longer being updated. Thanks for reading!
I get it, you hated — or hate — auto layout. Having interface builder assault you with blue and orange lines while you tried to merely nudge a label to the left was too much. Trying to analyze a 40+ line log message when a constraint broke was infuriating.
But now, trying to fight auto layout is a losing battle. It’s also tied permanently to using adaptive design, so it’s become a “must learn” at this point. The biggest bonus we can have as developers is reaching more users — and at it’s heart, that’s the mission of adaptive design.
Learning the basics and eventually becoming very comfortable with it will be paramount for iOS developers going forward. In this post, we’ll look at the big ideas behind it. After those sink in, visit the links after each section to learn more about the respective concept.
You need to understand…
Size Classes
When you first open up a storyboard in Xcode 6, you may be a bit confused. Did you miss the announcement for the iPhone Square? Thankfully, no! You are just seeing the idea of size classes in practice. See how it says “wAny hAny” at the bottom?
Go ahead and click it:
That blue grid represents any size and flavor you can experience iOS — be it the iPad, iPhone 4, all of it. Click around to change the values. Xcode handily shows you which device(s) you would be designing for.
What’s this mean? A universal storyboard, essentially.
When you are editing on any given view controller, those constraints and views trickle down to the other size classes. So when you add a constraint on a view with “wAny hAny”, that will apply to every single size class. Same goes for the other size classes as you select more specific ones.
Think about that for a second.
Need to make that UI just look a little different on that tiny iPhone 4S? Just open up that size class and tweak it out how you want. You can have an entirely different UI from size class to size class. All in one storyboard.
To make life even better, you can open up the assistant editor, choose preview — and like magic: a live rendering of your UI is shown as it would be at run time. Click the “+” at the bottom and you can add as many devices as you want.
You can override prepareForInterfaceBuilder and even give a view some dummy code to display. This method has no effect on a live app, so you can dedicate purely for debugging and design purposes. Xcode even gives you a new debugging option if you navigate to Editor -> Debug Selected Views.
As a bonus, if you add IBDesignable above your custom UI classes they will live render inside interface builder as well. This also applies to properties if they are tagged with the IBInspectable atribute.
Want more on the subject? Dig deeper here.
You need to understand…
UITraitCollection
All of that interface builder magic is great — but what about that 100% code driven UI? Apple didn’t forget about you either. You are going to essentially have the same power all in Objective-C and Swift.
Enter the new protocol UITraitCollection. In iOS 8, all view controllers conform to it. It gives you all the size class information you need at runtime. By simply looking at the collection, you can be aware of the size class presently displayed, the display scale, and even device type.
If for any reason you want to switch out the size class being presented, you can easily do that by creating an NSArray of the traits you want and passing them to traitCollectionWithTraitsFromCollections:.
With this kind of power inside a view controller, you can respond to any device and supply the appropriate UI. Remember, a device usually doesn’t have static size classes. For instance, the iPhone 5 has a regular vertical size class but a compact horizontal one.
So, to deal with those changes, traitCollectionDidChange: will fire off. Inside this method, just look at the new size class inside the trait collection and do what you need. No more worrying about orientation or the device, the trait collection will tell the whole story, all in one collection.
That’s the main idea, to get the entire picture go here.
You need to understand…
UIPopoverPresentationController
So this one is a neat trick. How many times have you seen code where it checks the type of device being displayed, and based off that show a different view controller or popover? WIth iOS 8 — that’s no more.
The idea here is that you ask the view controller for it’s presentation controller. After you present it, it’ll take the correct course of action for you. Typically on an iPhone, you’ll get a modal view controller presented. On an iPad, it’s going to be a popover.
UIViewController *contentVC = //contentif([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
UIPopoverController *popVC = [[UIPopoverController alloc]
initWithContentViewController:contentVC]; [popVC presentPopoverFromBarButtonItem:item permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];}
else
{
[self presentViewController:contentVC animated:YES completion:nil];
}
The end user won’t see any difference, but your code base will. Get all the details about how to implement it here, it’s the first video on the list. By the way, I find it helpful to keep that PDF around. It has great code samples.
You need to understand…
Size Class Dependent Images
This one is simple, in addition to have @2x images, we now have @3x for those juicy mega super ultra HD iOS screens. Like before, you don’t need to specify when and where to use those images, iOS grabs the right one for you.
If you don’t have the preferred image, it just goes down the tree. So on a iPhone 6+, if your binary is missing the given @3x image, if the @2x is there it’ll just use that. And, I hope this isn’t the case, but if that isn’t there it’ll grab the nasty, gross, low res image. Be sure to use the .xcasset folder for all of your media, which was introduced in iOS 7.
As a small aside here, with iOS 8 there is no longer a need to supply several launch images. You can now specify a dedicated .xib to launch. That, coupled with auto layout, will cover all the launch scenarios for you.
You need to understand…
Dynamic Text
This isn’t so much an entire API, or new for that matter, but it does lend itself to the idea of adaptive design. With dynamic text, you have your font respond to settings inside iOS. If the user wants some gigantic text, if your app utilizes dynamic text, the user is going to get what they want. If you don’t use it, well, then they won’t.
You can do some really cool stuff here as well, like having text wrap around images and the like. There are some tricks you can pull out of your sleeve to produce some very rich text experiences for the end user.
What is new, however, is being able to tie in your font sizes to size classes. Inside interface builder, you can set a font scale. This is great, because on smaller screens you can dictate what the minimum font size, or scale, should be. Then, when the user has your app on the enourmous iPhone 6+, you’ll rest easy knowing that you supplied a larger font size just for that device.
Get all the dirty details right here.
And yes, you most definitely need to understand…
Auto Layout
It doesn’t always make sense to use auto layout, but honestly, most of the time it does. You really have no choice but to use it anymore. With all of that adaptive design advancements, it’s just too easy to make a universal binary. But again, you really can’t do that without auto layout.
It’s also much easier with Xcode 6. You have complete control over your constraints since you explicitly add them. If you don’t, each view’s auto resize mask will be translated into constraints at run time. In code, you can always use the visual format language. More on that from Apple, and I’ve also written an introductory tutorial over the topic here.
Starting out, the technology can be difficult to learn. Instead of setting a frame, instead think about describing a relationship. You need to describe where the view should be and how large or small it can get. Don’t get overwhelmed with priorities and such, once you start to understand auto layout it becomes clear when and where to use those advanced techniques.
As someone who really struggled with comprehending auto layout, let me give you a course of action to learn it. This is what made it “click” for me. Clear out an afternoon and watch all of these videos in the order listed. After that, just keep using auto layout. It’s a use it or lose it type of thing, so don’t step away from auto layout too long lest you lose all your new found knowledge.
Wrapping Up
Knowing what adaptive design is and what it entails is both essential and exciting. Apple’s docs, by the way, have a nice page of links covering most of this. I suggest you go ahead and look at the detailed resources I listed after each section, and then get off your butt and start creating universal apps☺!
Jordan Morgan is an iOS software engineer who runs Dreaming In Binary.
@jordanmorgan10.