Xcode6からSizeClassesという概念が加わったのと、AutoLayoutも微妙に変更されていて謎のMarginが出るようなので調査した結果をまとめました。
SizeClassesとは
Xcode6からAutoLayoutに加え、SizeClassesという概念が加わりました。
Xcode5では、Universalアプリを作るには、iPhone向けとiPad向けのStoryboardをそれぞれ用意していましたが、Xcode6/iOS8からは、一つのStoryboard(あるいはXib)で対応させてしまおう、というのがSizeClassesです。
考え方としては、iPhoneやiPadの特定のサイズではなく、抽象的なサイズを扱うということです。ですので、今まで以上にAutoLayoutの制約によるレイアウトデザインが重要になります。
注目すべきは赤枠で囲った2箇所です。
まず右側。StoryboardのFileインスペクタを開くと、Use Auto Layout
の下に、Use Size Classes
という項目が増えており、デフォルトでチェックされています。SizeClassesを使う場合にはこちらをチェックしたままにします(ちなみにSizeClassesだけ使ってAutoLayoutを使わないということはできません)。
続いて下側。 wAny hAnyとなっています。 wはWidth(ウィドゥス)、すなわち横幅で、hはHeight(ハイト)ですね。Anyはどんな大きさでもという意味で使っているのだと思います。ここをクリックすると、Viewのサイズを変更できるバルーンが出てきます。
キャプチャは付けませんが、wCompact hRegularなども可能です。wCompact hCompactは、Apple Watchの開発環境もXcodeであることを暗に示しているようですね。
Xcode6でのStoryboardの使い方
SizeClassesを利用するに向けて、プロジェクトの作成時に特に意識することはありません。これまで通り、必要事項を入力し、DevicesでUniversalを選択します。
すると上で紹介したStoryboardのスクリーンショットと同じ画面が現れます。
では実際Constraintsの設定を見ていきます。ここでは例として、親View全体にUIWebViewを配置する、を実現します。ViewControllerのコードやOutletの設定に関する説明は割愛しますので、知りたい方はこちら(GitHub)からソースコードをダウンロードして下さい。
また、AutoLayoutに関する前提知識としてiOS7からステータスバーにViewが被るようになった、その解決策としてTop Layout GuideやBottom Layout Guideが導入されたことを知らない、良く分からない人はそちらも事前に調べておきましょう。
まず失敗例から
View全体にWebViewを配置して実行すると、iPhone5sの大きさだと残念ながら以下の様な結果になります。
表示しているのはうちの会社のトップページですが、横幅が切れています。これは別にレスポンシブ対応を行っていないから切れているのではなく、ViewよりもWebViewが大きく設定されているためです。
こんな感じになってしまっています。
ちなみにSafariで見るとちゃんと見ることができます:-)
失敗例その2:Xcode5までのノリでやると…
ではConstraintsを設定しましょう。ステータスバーにかからないようにするには、WebViewをView全体ではなく、上だけステータスバーの20px分小さくするのがミソでした。
エディタエリア右下のアイコンの中から「Pin」をクリックしてバルーンを表示します。
すると左右が-16となっています。Xcode5ではここは0になっていて、0にするのがセオリーでした。なので0にしてみます。上下に関しては、プルダウンをクリックし、Top Layout GuideあるいはButtom Layout Guideを選択します。
View Controller Sceneは以下の様になります。
意気揚々とシミュレータを実行すると、
左右にマージンが入ってしまっています!!
原因と解決策
気になったので、Xcode5で同じ手順で作ったものを、Xcode6で開いて比べてみました。比較した箇所は左右のConstraints(Horizontal Space)のAttributesインスペクタです。
Second Itemの項目に Marginが!!これが「-16」の正体ですね。
プルダウンを開いてみました。
こいつが犯人ですね。どうやらiOS8からViewのBoundだけではなく、設定されたMarginに対してConstraintsを設定できるようになったようです。
−16を設定するのではなく、Relative to marginを外しましょう:-)