One Storyboard to Rule Them All
At WWDC 14, Apple introduced Unified Storyboards and Size Classes. With a single universal storyboard, it’s now possible to design layouts for iPhones and iPads, in landscape and portrait, from a single nib. I like the idea of a single resource for all devices, but Apple’s implementation falls short for practical use.
Specifically, I’m coding an app UI now. No, not Three Straight – a new app in partnership with taptaptap. This app has quite different iPhone 4 and iPhone 5 layouts. With Size Classes, iPhone 4 & 5 are indistinguishable. If I have to hand-code the iPhone 4 constraints, I might as well hand-code everything. So, I’ve abandoned Size Classes for this project.
Before you say, “Change the iPhone 4 layout to match the iPhone 5, stupid!” let me point out that this design was created by a very well-respected designer, Wolfgang Bartleme, whose work includes Camera+, Convert, and Fantastical. I’m the developer. Wolfgang is the designer. It’s not my prerogative to change his design. Furthermore, if the tool constrains the design, then Size Classes is not the right tool.
But it’s close.
But but but … what about the iPhone 6 !?!
I get why Apple is pushing Unified Storyboards. We currently have six* screen variations to design for. Rumors of a new supersized iPhone, the mythical iWatch, and split-screen multitasking iPads suggest an explosion of screen sizes in the near future. Also, the new Xcode emulator supports arbitrary sized devices – a sure sign of the geometric spacial chaos to come.
The current Size Class definition yields 9 generic layout variants: Any/Compact/Regular for both height and width. In either dimension, Regular & Compact layouts inherit properties from Any, but can override constraints for custom layouts.
Initial layout is done in Interface Builder, using [Any,Any]. Variant layouts for iPhone vs. iPad, portrait vs landscape, are done by changing constraints in variants such as [Any,Compact], or [Regular,Regular].
Great! But again, there’s no way to distinguish iPhone 4 from iPhone 5 with these generic variant definitions.
This leaves me in a position of guessing, without confidence, what my layout will look like on a new super sized iPhone 6. Without hard info on the iPhone 6 resolution, this is the best I can do. But given the unacceptable results for iPhones 4 & 5, I will undoubtably be modifying the iPhone 6 layout once it ships.
A Modest Proposal
This proposal extends Size Classes, making them more practical for real-world applications, while retaining the intended flexibility of dynamic layout.
I propose additional Size Class definitions for specific devices and orientations. Each inherits properties from a generic variant, but can change constraints for device-specific designs:
iPhone 4 Portrait: “~iphone-portrait”, inherits from [Compact w, Regular h]
iPhone 4 Landscape: “~iphone-landscape”, inherits from [Compact w, Compact h]**
iPhone 5 Portrait: “~568h-portrait”, inherits from [Compact w, Regular h]
iPhone 5 Landscape: “~568h-landscape”, inherits from [Compact w, Compact h]**
iPad Portrait: “~ipad-portrait”, inherits from [Regular w, Regular h]
iPad Landscape: “~ipad-landscape”, inherits from [Regular w, Regular h]
These new Size Class definitions provide device-specific control of layouts. Developers are encouraged to work with generic layouts, and only use device-specific Size Classes when necessary.
When a new device is introduced, like a new super-sized iPhone perhaps, then Apple creates new Size Class definitions:
“~iphone6-portrait”, inherits from [Compact w, Regular h]
“~iphone6-landscape”, inherits from [Compact w, Compact h]
An existing app will not know about the “iPhone6” layouts, and will lay out using the generic variants [Compact w, Regular h] or [Compact w, Compact h]. If this is good enough, then generic layout wins! But if the new device calls for a new design, a developer can release an update with specific layouts for iPhone6-portrait and iPhone6-landscape.
Similarly, split-screen multitasking was recently unearthed in iOS 8. These odd layouts are handled with new Size Class definitions:
“~ipad-landscape-half”, inherits from [Regular w, Regular h]
“~ipad-landscape-third”, inherits from [Compact w, Regular h]
“~ipad-landscape-quarter”, inherits from [Compact w, Regular h]
“~ipad-portrait-half”, inherits from [Regular w, Regular h]
And even the mythical iWatch gets a definition, for the app extensions we all hope to write:
“~mythicalWatch”, inherits from [Compact w, Compact h]
Practical, but Unclean
My proposal dirties up Apple’s clean, generic Size Class definitions. But here’s the thing: Designers know best. When a designer calls for a device-specific layout, the tool has to handle it. Size Classes can’t handle my current design, and I see plenty of problems with future screen sizes. Therefore, my tool is Objective-C. Ugh. But until Apple fixes Size Classes, I don’t see a any other solution.
(*) the six existing screens are: (iPhone4/iPhone5/iPad x Portrait/Landscape). When presenting content on an external display via an Apple TV, there are two more: 1080p and 720p.
(**) this should probably be [Regular w, Compact h], but that’s a separate discussion. In fact, I suspect this odd definition is an artifact of attempting to fit specific device screens into generic Size Class definitions – something my proposal addresses.