2020年5月30日土曜日

iPhoneアプリのiPad対応1 - SplitView

iPadOSMac Catalyst のお勉強として、既存のiPhoneアプリ Recipe Note のiPad対応を試し中。WWDC 2020 でなにか進展がありそう予測も兼ねた復習として。
学んだこと、迷ったことを書いてみる。

OSになるべく逆らわず、以下の基本方針で。

  • iPhone/iPad で同じUI(Storyboard)を使う
  • UIDevice.currentDevice().userInterfaceIdiom でOSの条件分岐しない
  • Size Classでの条件分岐しない

UISplitViewController

iPadOSでSplit Viewの操作をすると、大きいサイズ(Regular) ⇔ 小さいサイズ(Small) が頻繁に切り替わることになる。
その操作をしても、いい感じの表示にするには、やはりUISplitViewController を使いたい。



UISplitViewController を使うポイント

状態の設定と取得

SplitViewの種類は、preferredDisplayMode で設定できる。
Master/Detailを両方表示(例: 設定アプリ)や、MasterをOverlay表示など。
isCollapsed で折りたたまれているかどうか?を取得できる。

displayModeButtonItem を、navigationItem.leftBarButtonItem に設定することにより、Back / 全画面表示 の処理をするボタンが表示できる。上記動画の右ペインの左上にあるボタンがそれ。状態によって表示も自動的に切り替わってくれる。

サイズに関する挙動差

Master(左ペイン) → Detail(右ペイン)と画面遷移していく、それらの画面がどこにStackされるのかは、Splitの表示状態によって異なる。
サイズがSmall、つまり1ペイン表示のときは、MasterのUINavigationViewControllerにStackされ、サイズがRegularのときは、UISplitViewControllerにStackされる。

iPhoneのときは初期表示をMasterのみにする

UISplitViewControllerのDetailにViewがあると、デフォルトでは初期表示はDetailになる。
iPhoneのときは初期表示をMasterのみにしたい場合は、UISplitViewControllerDelegate の splitViewController(_:collapseSecondary:onto:) で制御する。

Masterのみにしたい場合、false を返せばOK。
このメソッドは、iPhoneの初期表示だけでなく、サイズがRegular → Smallに変わった場合にも対応する。

ちなみにMasterのViewControllerにSplitViewのDelegateを設定したい場合、delegateの設定をviewLoadでしても間に合わないので、awakeFromNibで行う。(が、SplitView継承してカスタマイズする方がよいかもしれない)

Small → Regularに変わったときのDetailの指定


上記のコードでは、MasterのUINavigationViewControllerがTopのときは「なにも設定されていないView」をDetailに設定、それ以外はデフォルト = 表示されていたViewがDetailに表示 するようにしてみている。


当初は、「なにも設定されていないView」を使わない方法でアレコレ試していたが、いろんなパターンに対応するのは大変なので、使用する形の方が素直に実装できると思った。

Tabをデフォルトの挙動に合わせる

今回、Tabの中にSplitViewを入れる形で実装を進めているのだが、そうすると動かくなった機能がある。
  1. Hide Button Bar on Push (タブを非表示にする設定)
  2. TabItemタップ時、NavigationのTopに戻る
1については、setNavigationBarHiddenを使って自前で制御するしかない予感。iPhoneのときのみタブを非表示にしようかとも思ったが、無理に制御しないほうが無難かもと思い中。

2については、UITabBarControllerDelegate で以下のコードをいれてみた。

折りたたまれているときは、NavigationをRootに遷移。折りたたまれていない + Masterが非表示の場合には、Masterを表示する。(preferredDisplayModeにはallVisibleを設定している)

ちなみに、SplitViewのドキュメント
Split view controllers are normally installed at the root of your app’s window.
とあるので、Window Root以外にSplit Viewを使うのは推奨されていないかもしれない。


今回はここまで。
次回はSplitView以外のことを書いていこうと思う。
• • •