How can Xcode 6 adaptive UIs be backwards-compatible with iOS 7 and iOS 6?
Xcode6Adaptive UiXcode6 Problem Overview
I just watched the WWDC video #216, "Building Adaptive UI with UIKit."
At about 45:10 Tony Ricciardi talks about changes to IB in Xcode 6 to support the new changes.
He says "You can deploy these documents backwards to older versions of iOS".
(where "These documents" presumably means XIBs and storyboards that have specific settings for different size classes.)
I'm not making this up. Go watch the WWDC video.
How is that possible? Trait collections and size classes are only defined in iOS 8. How can runtime behavior that's dependent on UI constructs that are new to iOS 8 work in previous iOS versions?
If it is possible it would be wonderful. You could build apps that will run on iOS 6, 7, and 8, and take advantage of the new flexible UI layout abilities that Apple has added to Xcode 6. I've created adaptive UI logic myself in code, and it's quite a bit of work.
Xcode6 Solutions
Solution 1 - Xcode6
Changes made to the UI with Size Classes in Interface Builder DO appear correctly on iOS 7 devices and the Preview in Xcode. For example, I changed some Auto Layout constraints and font sizes for Regular height Regular width and those changed constraints are visible in the iPad Simulator running iOS 7.0.
All size class optimizations are made available to iOS 7, except size classes that have a Compact Height. This has been confirmed by Apple and is now stated directly in the documentation:
**For apps supporting versions of iOS earlier than iOS 8, most size classes are backward compatible.
Size classes are backward compatible when:
- The app is built using Xcode version 6 or later
- The deployment target of the app is earlier than iOS 8
- Size classes are specified in a storyboard or xib
- The value of the height component is not compact**
Because iOS 7 doesn't respect a couple of size classes, if you use them you'll run into issues. For example: When you have Compact w Any h defined and then Compact w Compact h defined, on iOS 7 it will respect the Compact w Any h but on iOS 8 it renders the Compact w Compact h appearance.
So, if you would like to utilize those two size classes and maintain compatibility with iOS 7, I would do any optimizations you desire for iPhone in landscape in Any w Any h or Compact w Any h, then perform your other optimizations for different size classes as necessary, and that way you won't need to use any size class with compact height and will avoid running into issues.
Solution 2 - Xcode6
When deploying your app to iOS 7, Xcode will compile your storyboard in two different ways:
-
For iPhone, your storyboard gets compiled as "Compact-Regular" (Compact width, regular height), and this gets packaged as your "~iphone" nib.
-
For iPad, your storyboard gets compiled as "Regular-Regular" and gets packaged as your "~ipad" nib.
So if you're looking to deploy to both iOS 7 and iOS 8, you should focus your design on the Compact-Any and Regular-Any size classes. That will give you the best experience in terms of matching the UI across deployment targets. You are, of course, welcome to modify the layout for other size classes, but unless those modifications would get applied to the Compact-Regular or Regular-Regular size classes, then you would not see those modifications on iOS 7.
Solution 3 - Xcode6
Note: This answer was relevant to a beta version of Xcode 6 and is no longer applicable to the shipping version. See answers by Joey and Dave DeLong on this page for proper information.
(original answer retained below):
While Storyboards/XIBs
configured to use size classes will run on iOS 7
, the OS does not currently respect those size classes
and appears to use the default 'Any/Any' size class.
I agree that the particular slide you are referring to seems to promise such compatibility, but it doesn't appear to be the case currently (Xcode 6 beta 2)
.
To test, I created a project (iOS 8 SDK, deployment target of 7.1)
with a single button that is centered vertically and horizontally
in the Any/Any size class, but aligned to the top left corner in the Compact/Compact size class (e.g. iPhone in landscape). Xcode's Preview Assistant shows that the button changes its position in iOS 8
, but not iOS 7
. I confirmed this behavior on an iOS 7
device as well.
Solution 4 - Xcode6
As some of the answers and comments were discussing the nature of backwards-compatibility, I thought I would share an excerpt direct from the [Apple Documentation][1]:
#Deploying an App With Size Classes on Earlier iOS Versions
**For apps supporting versions of iOS earlier than iOS 8, most size classes are backward compatible.**
Size classes are backward compatible when:
- The app is built using Xcode version 6 or later
- The deployment target of the app is earlier than iOS 8
- Size classes are specified in a storyboard or xib
- **The value of the height component is not compact**
~~~~~<br/><br/>
That last bullet point is targeted at this discussion, where Apple confirms that **as long as "compact height" is *not* used**, it should maintain backwards-compatibility.
Hope this helps someone!
[1]: https://developer.apple.com/library/ios/recipes/xcode_help-IB_adaptive_sizes/chapters/DeployingSizeClassesonEarlieriOSVersions.html#//apple_ref/doc/uid/TP40014436-CH13-SW1
Solution 5 - Xcode6
While dealing with the similar issue I found another answer that I haven't seen here yet. Looks like Size Classes in XIB
files are not working at all. If I create cell prototype in the storyboard
file it works in iOS7 as explained in other answers, however when the same prototype cell is moved into separate XIB
file - size classes are ignored in iOS7.
Here is link to the sample project demonstrating this behavior: https://dl.dropboxusercontent.com/u/6402890/testSizeClasses.zip
In the prototype cell I have four constraints from each edge of the grey view. Each of the is configured in a same way: Any/Any - 10, Regular/Regular - 20
It works fine in iOS8 simulator for both XIB and Storyboard, and in iOS7 only cells defined in Storyboard gets updated constraints on iPad:
Solution 6 - Xcode6
If it saves anyone time, I believe that the way Xcode 6 provides quasi-backwards compatibility for size classes is via the historical ~ipad
and ~iphone
suffixed storyboards, and nothing more. This makes sense since size classes are a more abstracted way of how we previously defined an iPad storyboard, and an iPhone storyboard.
Therefore:
-
If your goal is to use size classes to support device family specific layouts (iPad vs. iPhone), then you are in luck: size classes are a nicer interface to the previously supported method.
-
If your goal is to use size classes to support altered layouts for different models within the same device family - ie. iPhone 5/6/6+ inc. landscape, then you are out of luck. Using these would require a minimum iOS 8 deployment target.
Solution 7 - Xcode6
@lducool - In interface builder, in the Identity inspector, change 'Builds For' to iOS7.1 and later.
Solution 8 - Xcode6
Unfortunately the answers from Dave and Joey do not work for me. I am not allowed to comment in this thread, so please forgive me if this is the wrong place.
I have made up a specific question for that: https://stackoverflow.com/questions/26694627/example-for-iphone-portrait-landscape-adaptive-ui-which-is-backwards-compatible
From what I learned so far, I believe now that, like in my example, is is not possible to have 2 separate, different constraints for one ui element in portrait and landscape mode with iPhone iOS7 based on size classes. Would be glad if I am mistaken, though.