SH Lab の アプリ開発部屋

リリースしたアプリの告知とかサポートとか、技術的なお話とか、そんな感じでつぶやきます。

Storyboard Reference がいい感じ

勉強会で持ち帰ったトピックが気になった

先日参加した iOS 9 の勉強会にて、岸川克己さん@Realm が話された Storyboard Reference の話が非常に興味深かったので、自分なりに追加調査してみました。

dev.classmethod.jp

まずはstoryboardの欠点とか

storyboardは、xibでの開発と比べて、画面の遷移が視覚的に分かりやすいのと、segueを利用できるという利点があります。ですが、ファイルが1つなので、チーム開発を行うと競合しやすく、分業しづらいという欠点があります。

そのため、segueを利用できるという利点を破棄してでも画面ごと機能ごとにstoryboardを分割する、という手法が選択されがちだと思います。

分割した別のstoryboardを利用するためには、プログラム側でいろいろやる手間が発生してしまいます。遷移にsegueは利用できず、視覚的にも伝わりづらくなってしまうので、出来れば避けたいですね。

ちなみに、storyboardについてあまりご存知ない方は、この辺りを参考にしてみるといいかもしれません。


ぼっち開発でも困る時は困る

自分のように1人で作業する分には、分業を考える必要はあまりありません。ですが、1つのstoryboardファイルが膨れ上がってしまうのは、やはりあまり嬉しい状況ではないですね。

ちなみに、自分がリリースしている某アプリのstoryboardはこんな感じで、晒すのも恥ずかしいくらい管理が行き届いておりません...

f:id:hoshi0523:20151003190542p:plain

ですが、Xcode 7 からは、この欠点を補うべく、Storyboard Reference という機能が追加されました。


Storyboard Reference とは?

Storyboard Reference は、分割したstoryboardファイル同士を参照し、segueでつなぐことができる機能です。

つまり先ほど挙げた、ファイル分割時の欠点が補われるということですね!

  • 別のstoryboardへの参照もsegueで記述できる
  • 遷移のためのプログラム記述は不要


とりあえず使ってみた

まずは今まで通りに

まずはこんな感じで、画面Aのボタンをタップすると画面BにPUSH遷移を行う、というstoryboardを作ってみます。これまで通りで、特筆すべき点は無いですね。

f:id:hoshi0523:20151003213830p:plain


別のstoryboardファイルを作る

次に、別のstoryboardファイルを生成します(Green.storyboard)。そこに、ViewControllerを1つ配置して、コレを Initial ViewController とします。この画面は画面Cとします。

f:id:hoshi0523:20151003214306p:plain


Storyboard Reference を使う!

画面B上にボタンを配置し、このボタンをタップしたら画面Cに遷移するようにしましょう。

Main.storyboardに、右下のオブジェクト一覧から、storyboard reference をドラッグして配置します(①)。

この Storyboard Reference が Green.storyboard を参照するように設定します(②)。

画面B上のボタンから、この Storyboard Reference に対してPUSH遷移のsegueを設定します(③)。

f:id:hoshi0523:20151003220411p:plain

これで動かしてみれば、画面A画面B画面C の順番で遷移していくと思います。

f:id:hoshi0523:20151003222310g:plain


既存のファイルを分割する場合は?

自分のアプリのように、すでに膨らんでいるstoryboardを分割するのも、編集メニューから簡単に行うことができます。

今回は、Main.storyboard画面B を、別のstoryboardファイルとして分離してみます。


storyboardを分割するよ

分離したいオブジェクトを選択した状態で(①)、Editor → Refactor to Storyborad ... を選択します(②)。

f:id:hoshi0523:20151003223527p:plain


新しくstoryboardが生成された

そうすると、新たにstoryboardが生成されます!(ファイル名は Blue.storyboard としました。)

中には 画面B の ViewController があって、そこから Green.storybard に遷移できるようになっているみたいです。想定通りですね。

f:id:hoshi0523:20151003224155p:plain


元になったファイルも変更されてますね

分割元となった Main.storyboard も、正しく変更されているようです。

見てみてると、画面A の ViewController のみになっており、画面B の代わりにStoryboard Reference が配置されています。これは、先ほど生成された Blue.storyboard を参照しているようです。

f:id:hoshi0523:20151003224803p:plain

この方法を使えば、すでに膨らんでしまったstoryboardファイルを抱えて悩んでいる方も、簡単にファイルを分割できそうですね〜。


iOS 9 のみで使える機能なの?

ちなみに、この Storyboard Reference は、どのバージョンのiOSをサポートしているのでしょうか...?

今回作成したアプリは、Deployment Target を 9.0 にしていましたが、これを 8.0, 7.0 に変更してビルドしてみます。

f:id:hoshi0523:20151004004412p:plain

f:id:hoshi0523:20151004003645p:plain

どうやら、Storyboard Reference は、iOS 8.0 以降の機能っぽいですね。


Relationship Segue も行けちゃう

Navigation ControllerTab Bar Controller のようなコンテナ系の ViewController には、関係性を定義する Relationship Segue というsegueを設定します。これらにも、Storyboard Reference を利用できます。


ベースにあるNavigation Controller

ベースには Navigation Controller を配置しています。Navigation Controller の場合は、Relationship Segue を利用して Root ViewController を設定する必要があります。

今回は Storyboard Reference を利用しているので、Root ViewController には、別のstoryboardファイルに定義された ViewController を設定しています。

f:id:hoshi0523:20151004014317p:plain


Tab Bar Controller が中にいる

Navigation Controller の Root ViewController には、Tab Bar Controller を設定しています。当然、この Tab Bar Controller は、Initial ViewController として設定されています。

Tab Bar Controller にも、Relationship Segue を利用して、各Tabの ViewControllers を設定する必要があります。ここも Storyboard Reference を利用し、別のstoryboardファイルに定義された ViewController を複数設定しています。

f:id:hoshi0523:20151004014649p:plain


各タブごとの ViewController

各タブに利用している ViewController は、一つのstoryboardファイルにまとめて定義しています。

f:id:hoshi0523:20151004015202p:plain

...あれ?Initial ViewController が定義されていなくね?ちゃんと呼ばれるの??と、思う方もいるかもしれません。

Storyboard Reference を利用する場合は、ここまで説明し的してきた「利用するstoryboardファイルを指定して、Initial ViewController に設定されたViewControllerを呼び出す方法」「利用するstoryboardファイルと、利用するViewControllerの Storyboard ID を指定する方法」の2通りあります。


Storyboard ID を使う場合

1つのstoryboardに複数のViewControllerを定義している場合は、後者の方法を採用することで、利用するViewControllerを使い分けることができます。

その場合、各ViewControllerには、それぞれ一意となる Storyboard ID を定義する必要があります。

f:id:hoshi0523:20151004021145p:plain


そして、それらのViewControllerを利用するStoryboard Referenceには、storyboardファイル名とReference ID(Storyboard ID)を設定します。

f:id:hoshi0523:20151004021200p:plain


これを iOS 8 で利用しようとすると...

先ほど調査したように、Storyboard Reference は iOS 8 以降で使えるんだよな〜と思っていると...怒られました

f:id:hoshi0523:20151004022441p:plain

どうやら、Relationship Segue に対して Storyboard Reference を利用する場合は、Deployment Target が 9.0 以降である必要があるみたいですね。

ということで、iOS 8 系をターゲットとするアプリの場合は、relationship segue に対して Storyboard Reference を利用しないようにしましょう!


分割しちゃうと unwind segue って使えないの...?

個人的には、モーダルを閉じる際に unwind segue を使うのですが、ファイルを分割しちゃうと使えなくなっちゃうでしょうか...?ちょっと試したんだけど、やり方がわからなかったです。

設定画面はモーダル表示で、Storyboard Reference を使うぞ! みたいなことって、割と普通にありそうなのですが、こういう場合は unwind segue は諦めろってことなのかな...?

この件に関しては、もう少し調査しないといけないですね(汗)


早く使いたい機能だよ。iOS 7 とか切りましょうよ。

ということで、Storyboard Referenceは、とても魅力的で開発にも良い効果を与えそうな新機能でした。チーム開発を行っている現場では、特に重宝されるんじゃないですかね。

ただ、この機能を導入するには、最低でも iOS 7 のサポートを終了する必要があります。サービスへの影響は小さくないかもしれませんので、サービスの規模によっては、慎重にならざるをえないかもしれませんね...

ちなみに、自分の某アプリのiOSバージョン分布はこんな感じでした。

f:id:hoshi0523:20151004023547p:plain

もう iOS 7 切ってもよくないっすか?