iOS Size Classesを利用してユニバーサル対応を行った話

こんにちは。AirレジのiOSアプリ開発を担当している山口です。

Airレジは昨年5月に行ったリニューアルに伴い、ユニバーサル対応を行いました。それまではiPhone/iPadで別アプリとして管理していましたが、ユニバーサル対応によりメンテナンスコストを下げることができました。

しかし、開発当初はSize Classesについての理解が浅いままユニバーサル対応を進めてしまい、レイアウト作成中に手戻りが発生したり、UIの共通化が上手くいかず分岐が複雑になってしまうなどの問題が発生していました。そこで、今回はSize Classesの概要とポイントについて書いてみました。

これからユニバーサル対応を始める方の参考になれば幸いです。

Size Classes

iOS8以降、多様化する画面サイズを抽象化して扱うための概念としてSize Classesが登場しました。様々なデバイスや向きに対応したAdaptive UIを実現する上で重要な概念となっています。AirレジはiPhone縦向き/iPad横向きの2パターンのみ対応していますが、メディア系アプリなどはAdaptive UIに対応することでより優れたユーザ体験を提供することができます。

Size Classesでは画面のwidth・heightそれぞれに対して、Compact・Regularサイズが定義されています。何十パターンにも及ぶデバイスサイズ、向きの違いを下図のように4パターンで表すことができます。

size_class.png WWDC2016 Making Apps Adaptiveより

Interface BuilderによるSize Classesの利用

Xcode8からSize Classesの使い勝手が大きく改良されました。ここでは、Interface Builderで実際にどのようにSize Classesを利用するかを書いていきます。

動作確認環境は、執筆時点で最新のXcode8.2.1となっています。

Device configuration pane

Interface Builder下部にdevice configuration paneが追加されました。ここでは、デバイス・向きを選択することで、現在設定されている設定や制約に応じた表示を確認することができます。Xcode7ではCompact・Regularなどサイズベースで選択していましたが、デバイスベースで選択できるようになったため、より理解しやすくなっています。

device_configuration_pane.png

各Size Class共通のレイアウト設定

Size Classesを利用したレイアウトを作成する上で、まずはベースとなるレイアウトを作成していきます。device configuration paneから、アプリケーションのメインとなるデバイス・向きを選択して作成していくとよいでしょう。Airレジの場合はiPadの横向きがメインなので、それをベースとしています。

main_layout.png

この状態で設定したViewやそのプロパティ・制約については、どのサイズにおいても適用されます(Xcode7でのwidth:Any・height:Any)。

other_layout.png

Size Class別のレイアウト設定

上記の例で、iPhone縦画面のようなwCompact・hRegularサイズのときだけ、青と赤のViewを縦並びにしたい場合などがあるかと思います。

device configuration paneから対象のデバイス(サイズ)を選択した状態で、Attributes Inspectorの「+」→「Add Variation」をクリックすることでwidth:Compact・height:Regularサイズの場合のみ縦並びにすることができます。この他にも、下記のような様々なプロパティに対してサイズ毎の設定を行うことが可能です。

  • フォントサイズ
  • View自体の表示・非表示(※isHiddenプロパティとは別)
  • AutoLayoutの制約 など

wC_hR_layout1.png

また、特定サイズだけ新たにViewや制約を追加したい場合は、device configuration paneの「Vary for Traits」をクリックした上でViewや制約を設定することで該当サイズの場合は有効、他のサイズの場合は無効とすることができます。

wC_hR_layout2.png

Size Classes利用時のポイント

Airレジでユニバーサル対応を行った際に得られたポイントや注意点をご紹介します。

デザイナーとSize Classesについて認識を合わせる

Size Classesについて深く理解しているデザイナーの方はまだまだ少ないかと思います。そうした場合、iPhone/iPadでデバイス別のレイアウト指示書などが納品されてくるかと思います。しかし、Size Classesの概念ではデバイスによる分類ができないため別途UIUserInterfaceIdiomを見てレイアウトを変えるなど条件が増えてしまったり、レイアウト自体を再検討する必要がでてきます。

事前にデザイナーとSize ClassesやAutoLayoutの概念について認識を合わせてから、レイアウト作成にとりかかるようにすることが重要だと感じました。

UIModalPresentationStyleの扱いに注意する

ViewControllerをモーダル表示する際のスタイルによって、ViewControllerに適用されるSize Classが異なるため注意が必要です。iPadの場合、UIModalPresentationStyle.formSheetではwidth:Compact・height:Regular、UIModalPresentationStyle.pageSheetではwidth:Regular・height:Regularとなります。

冒頭で述べたように、表示する画面サイズによってSize Classが定義されるため当然といえば当然ですが、同一デバイスであっても状況によって適用されるSize Classが異なってくるという認識をもつことが重要です。私は当初、iPad = width:Regular・height:Regularといった認識をしていたため、UIModalPresentationStyle.formSheetで表示した際に想定通りのレイアウトにならず痛い思いをしました。

Interface BuilderでのInstalledの扱いに注意する

Size Classに応じてViewの表示・非表示を切り替えるInstalledの設定ですが、対象のViewが表示されていない場合の状態は下記のようになっています。Viewの表示状態によって処理を分ける場合などは注意が必要です。

  • IBOutletで接続しているインスタンス自体は存在する
  • isHiddenプロパティがtrueになるわけではない
  • View階層から削除されるため、superview == nilとなる

おわりに

今後、iOSアプリを作成する上でAdaptive UIという考え方が重要になってくるかと思います。従来のようにデバイス種別や向きでレイアウトを区別するのではなく、表示される画面サイズによってレイアウトを区別するという認識をチーム全体で持つことが重要だと思いました。