SizeClassesとXcode6でのAutoLayoutの謎マージン

  • 299
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

Xcode6からSizeClassesという概念が加わったのと、AutoLayoutも微妙に変更されていて謎のMarginが出るようなので調査した結果をまとめました。

SizeClassesとは

Xcode6からAutoLayoutに加え、SizeClassesという概念が加わりました。

Xcode5では、Universalアプリを作るには、iPhone向けとiPad向けのStoryboardをそれぞれ用意していましたが、Xcode6/iOS8からは、一つのStoryboard(あるいはXib)で対応させてしまおう、というのがSizeClassesです。

考え方としては、iPhoneやiPadの特定のサイズではなく、抽象的なサイズを扱うということです。ですので、今まで以上にAutoLayoutの制約によるレイアウトデザインが重要になります。

Xcode6のStoryboard

注目すべきは赤枠で囲った2箇所です。

まず右側。StoryboardのFileインスペクタを開くと、Use Auto Layout の下に、Use Size Classesという項目が増えており、デフォルトでチェックされています。SizeClassesを使う場合にはこちらをチェックしたままにします(ちなみにSizeClassesだけ使ってAutoLayoutを使わないということはできません)。

続いて下側。 wAny hAnyとなっています。 wはWidth(ウィドゥス)、すなわち横幅で、hはHeight(ハイト)ですね。Anyはどんな大きさでもという意味で使っているのだと思います。ここをクリックすると、Viewのサイズを変更できるバルーンが出てきます。

wAny hAny

wConpact hCompact

wRegular hRegular

キャプチャは付けませんが、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で見るとちゃんと見ることができます:-)

Safariで見た場合

失敗例その2:Xcode5までのノリでやると…

ではConstraintsを設定しましょう。ステータスバーにかからないようにするには、WebViewをView全体ではなく、上だけステータスバーの20px分小さくするのがミソでした。

エディタエリア右下のアイコンの中から「Pin」をクリックしてバルーンを表示します。

Pin Constraintsのバルーン

すると左右が-16となっています。Xcode5ではここは0になっていて、0にするのがセオリーでした。なので0にしてみます。上下に関しては、プルダウンをクリックし、Top Layout GuideあるいはButtom Layout Guideを選択します。

Top Layout Guide

上下左右にConstraintsを追加

View Controller Sceneは以下の様になります。

View Controller Scene

意気揚々とシミュレータを実行すると、

左右にマージンが!

左右にマージンが入ってしまっています!!

原因と解決策

気になったので、Xcode5で同じ手順で作ったものを、Xcode6で開いて比べてみました。比較した箇所は左右のConstraints(Horizontal Space)のAttributesインスペクタです。

Xcode5
Xcode5

Xcode6
Xcode6

Second Itemの項目に Marginが!!これが「-16」の正体ですね。
プルダウンを開いてみました。

Xcode5
Xcode5

Xcode6
Xcode6

こいつが犯人ですね。どうやらiOS8からViewのBoundだけではなく、設定されたMarginに対してConstraintsを設定できるようになったようです。

−16を設定するのではなく、Relative to marginを外しましょう:-)

参考
StackOverflowでの似たようなQuestion
Configuring Content Margins