昨日はじめて知ったのですが、StoryBoardやXIBファイルはプロジェクトやターゲットのDeployment Targetとは別に、各ファイルごとに個別にDeployment Targetを設定することができます。
例えば、iOS 8以上にしか存在しないUIVisualEffectView
や、iOS 9以降でしか使えないUIStackView
をStoryBoardで配置して、プロジェクトのDeployment Targetを7.0(や8.0)にすると、下記のエラーでビルドに失敗します。
Main.storyboard: error: Class Unavailable: UIVisualEffectView prior to iOS 8.0
これを避けるためにはStoryBoardを使うことをあきらめ、コードでOSバージョンを分岐して、コードでUIコンポーネントを配置する必要があると思っていました。
しかし、StoryBoardにはファイルごとにDeployment Targetを設定できるので、新しいUIコンポーネントを配置しているStoryBoardについては、プロジェクトのDeployment Targetよりも高い値を指定します。
StoryBoardを選択して、File Inspectorの「Interface Builder Document」セクションの「Build For」がそれになります。
↑ たとえば、上記の例ではプロジェクトのDeployment Targetは7.0なのでiOS 8以上でしか使えないUIVisualEffectView
をStoryBoardで配置するとビルドエラーになりますが、そのStoryBoardのDeployment Targetを8.0以上にすることでビルドできるようになります。
もちろん、古いOSでStoryBoardを使ってしまうと実行時にクラッシュしてしまうので、OSのバージョンを判断して、ロードするStoryBoardを変更するようにします。
let storyboard: UIStoryboard if #available(iOS 9, *, *) { storyboard = UIStoryboard(name: "Detail-iOS9", bundle: nil) } else { storyboard = UIStoryboard(name: "Detail-iOS8", bundle: nil) } if let controller = storyboard.instantiateInitialViewController() { self.navigationController?.pushViewController(controller, animated: true) }
↑ このようにすると、古いOS用のUIと新しいOS用のUIがStoryBoard単位で分けられますし、レイアウトはStoryBoardが使えるので、スッキリした構成になります。
iOS 9ではUIStackView
を使い、古いOSではUICollectionView
を使うように切り替えるなども簡単にできます。
【参考】