読み書きプログラミング

日常のプログラミングで気づいたことを綴っています

iPadOSでポートレートとランドスケープで異なるレイアウトを採用する

iPadのサイズクラスはポートレートでもランドスケープでもwR hRなのでサイズクラスでは表題の件を実現できません。
これについてググると、traitCollectionをoverrideする方法が出てきます。wR hRのサイズクラスを縦横比に従ってwC hRもしくはhCに変えてしまおうというアイデアです。
(wR hCではなくhCなのは、wC hCがiPhone 4などコンパクトな機種でのランドスケープだからです)

ところが、iOS 13/iPadOS 13ではtraitCollectionのoverrideがnot supportedになりました。
なんとかしないといけません。

色々方法はありますが、拡張性を重視して以下の方法を採用しました。

  1. wC hR, hCについてストーリボードで制約を設計
  2. wR hRについてポートレートランドスケープそれぞれについてストーリボードで制約を設計。両方installedにすると衝突するので、メインと思われる片方のみinstalledにする。
  3. ルートビューコントローラにisPortraitというインスタンス変数を用意する
  4. ルートビューコントローラのupdateVIewConstraintsをoverrideしてwR hRの場合、isPortraitに応じて2で設計した制約のどちらかだけをactivateする。(wR hRでない場合には両方deactivateする)
  5. ルートビューコントローラのviewWillTransition(to:with:)をoverrideしてwR hRのときの縦横比からisPortraitの条件が変わった場合、isPortraitを設定してview.setNeedsUpdateConstraintsを呼び出す

これで色々な状況に対応できました。
色々とは、念頭にある回転だけでなく、例えば、アプリがフォワグランドに復帰するときとか、スプリットビューとか。

これだけ書くと当たり前っぽい処理ですが、ここに至る前にupdateVIewConstraintsをoverrideせずにviewWillTransition(to:with:)内で制約を切り替える方法を実装して嵌りました。updateVIewConstraintsはデフォルトでは色々な状況でストーリボードの制約を読み直す処理が入っているようで、viewWillTransition(to:with:)で設定しても有効にならないケースが複数ありました。

以上、ご参考になれば幸いです。
また、これに関してもっと常識のイデオムがあれば教えていただきたく。