Size Classとは?
- XCode5まではiPhone, iPad両方に対応するにはStoryboardを2つ用意する必要があった。
- XCode6ではSize Classが導入され、1つのStoryboardで複数のデバイス・デバイスの向きに対応できるようになった
- Size Classではサイズを3つの抽象的な値で指定する
- Compact
- Regular
- Any(Compact, Regularどちらでもよい場合)
- その3つの値を横方向(Horizontal)、縦方向(Vertical)に指定し、その組み合わせでどのデバイスのどの向きに対しての命令なのかを判別する
デバイス&向きの組み合わせをSize Classに振り分けた表
- ここにあった表、LadscapeとPortraitが逆になってました。。。ごめんなさい。。
- クラスメソッドさんの記事が非常にわかりやすいですのでそちらを見ましょう
できること
Storyboard上でできること
- Size ClassごとにAuto Layoutを指定する
- 「このAuto LayoutはこのSize Classで有効にする」という感じで設定する
- Size ClassごとにUIコンポーネントを指定できる
- 「このUIコンポーネントはこのSize Classの時に存在する」という感じで設定する
コードからできること
- UITraitEnvironmentプロトコルを実装すると、
- traitCollection(UITraitCollectionクラスのインスタンス)から現在のSize Classが取得できる
- traitCollectionDidChangeをoverrideすれば、Size Classが変更された時(デバイスの向きが変わった時)の処理を追加できる
無理やり使ってみた例
HorizontalがCompactの時にセンタライズ、Regularの時に右寄せにボタンを配置する
- サイズや位置はAuto Layoutで変更できるのでStoryboard上で完結できる
完成!シュミレータのiPhone6Plusで確認します。
HorizontalがCompactの時にボタンをDisableにする
- 活性・非活性、色、フォントサイズなど、Auto Layoutで変更できないプロパティは、
UITraitEnvironmentプロトコルを実装し、UITraitCollectionで向きを判定して操作する - ボタンを2つ用意して出し分ける方法でもできるけど、
レイアウトの変更が起きた時に2つ修正しないと行けないので辛い
import UIKit
// UITraitEnvironmentプロトコルを実装
class ViewController: UIViewController, UITraitEnvironment {
// Storyboardで配置したUIButton
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// レンダーされた時に初期値を設定する
// traitCollection.horizontalSizeClassで横方向のサイズを取得
// UIUserInterfaceSizeClassというEnumが返ってくる
button.enabled = traitCollection.horizontalSizeClass != .Compact
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Size Classが変更されたら実行される関数
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
// デバイスの向きが変わった時に再計算して設定する
button.enabled = traitCollection.horizontalSizeClass != .Compact
}
}
最初、勘違いしたこと
- 【勘違い】Storyboard編集画面の下部にある「wAny | hAny」ボタンでSize Classを選択し、
右パネルからプロパティを変更すればそのSize Classに対してプロパティを設定できるのかと思っていた- 【正解】あれは「どのSize Classでプレビューするか」のボタン