こんにちは、genesixで働くiOSエンジニア、@TachibanaKaoruです。

最近Web業界ではA/Bテストがすっかり定着してきます。

iPhoneアプリでもA/Bテストをしてみたいと思う方も多いと思います。
でも、AとBの二種類のパターンでユーザーインターフェースをデザインして、起動時にランダムでどちらかのパターンになるように実装して、アプリをリリースして、ユーザーのレスポンスを計測したあとで、また決まったユーザーインターフェースでアプリをリリースして……なんてことを考えると、ちょっと億劫になってきますよね。

そこで、アプリをリリースし直さずにiPhoneアプリのユーザーインターフェースを動的に変更する方法を実装してみました。
ここのユーザーインターフェースはどうしよう、ちょっとユーザーの反応をみて決めたいんだけど……と迷ったときに試してみてください。

サンプルソースはこちらにおいています。

ユーザーインターフェースを変更する(サーバーを使わない場合)

まずは、特にサーバーを使わない、簡単な方法です。

アプリのなかに複数のStoryboardを持っておけば、任意の時に、Storyboardを全部入れ替えることができます。

起動時に切り替えてもいいですし、ユーザーが選択したタイミングで切り替えてもいいですよね。

下記のように rootViewControllerを差し替えると、アプリ全体のユーザーインターフェースをまるまる変更することができます。

では、Storyboardをさしかえることで、なにができるんでしょうか。
ボタンや表示テキストの色や配色や位置など、画面のデザインやレイアウトを変えることができるのはもちろんですが、segueによる画面同士の遷移を変更することも可能です。
 
例えばトップ画面をタブ形式にするのか、それともテーブルビュー形式にするのかなどで悩むことも多いと思いますが、2パターンのStoryboardを作って、ユーザーの反応を測定してから決定することもできますね。
 

ユーザーインターフェースを変更する(サーバーを使った場合)

さて、さきほどの方法を使うと、アプリのUIをまるまる変更することはできますが、アプリの中に含まれたStoryboardファイルの内容を変更したり、数を増やしたりするためにはアプリを再リリースしないといけません。
 
これではちょっと柔軟性に欠けてしまうので、このStoryboardをサーバー側からとってくる仕組みにして、アプリの再リリースが必要ないようにしてみましょう。
サーバー側においておけば、いつでもStoryboardの内容を変更できますし、必要に応じて数を増やしたりすることも可能です。

まずは、Storyboardをダウンロードできるように、StoryboardがはいったNSBundleを作ります。
そして、そのNSBundleをzipにしてサーバーの適当な場所に配置します。

アプリ側では、そのzipファイルをダウンロード・解凍して、そのなかからStoryboardをとりだします。
あとはさきほどと同様に、rootViewControllerを変更すれば、アプリ全体のユーザーインターフェースを変更することができます。 
参考:Downalodable Storyboard

データ構造の変更に対応する

Storyboardで変更できるのは、画面のレイアウトやデザイン要素だけではありません。
実はStoryboardで、データ構造の変更に対応することもできます。

Storyboardでは、生成したオブジェクトのプロパティにアクセスできる「User Defined Runtime Attributes」という仕組みがあります。
 
例えば、この図に表示されているStoryboardのインスタンスはDITTableViewControllerというクラスのオブジェクトになっています。
普通にStoryboardで生成するだけでは、このオブジェクトのプロパティは初期化されただけの状態ですが、右の「User Defined Runtime Attributes」の部分に入力したい値をいれておけば、このオブジェクトが生成されたときに、指定した値が入力されます。

 44


この図の設定の場合には、下記のソースコードを書いた場合と同じ処理がStoryboardだけで実行されるわけです。


処理の流れとしてはこんな感じになります。
  1. DITTableViewControllerの初期化時にStoryboardで、APIのEndPointとして、「http://itunes.apple.com/jp/rss/topfreeapplications/limit=20/json」の値が設定される
  2. DITTableViewControllerのviewWillAppearで指定されたAPIのEndPointからJsonを取得し、かつ「feed.entry」で指定されたKey Pathの値をArrayとして内部に保持する

このAPIのEndPointと、表示データのArrayとして読み込むKey Pathの値をどちらもStoryboardで設定できるようにしておくことで、APIを変更した場合や、データベース構造が変更になった場合にも、Storyboardを差し替えるだけで対応できるようになりました。

また、画面に表示する要素も同じ仕組みで変更することが可能です。
この図では、UILabelを継承したDITLabelを使って、上記でダウンロードされたJsonファイルの中のim:artist.label要素を画面に表示するようにしています。

 UILabel

この仕組みを使うと、データベースの変更などにも、 Storyboardを変更するだけで対応することができます。

サンルコードのなかに、ソースコードを変更せずにStoryboardだけで「無料アプリリスト」と「映画リスト」をiTunesから取得して表示する画面を作ったので確認してみてください。 

測定

どのようにユーザーインターフェースをきりかえる方法を説明しましたが、A/Bテストで重要なのは確実な測定と分析です。

ユーザーインターフェース変更の仕組みをいれるだけではなく、それぞれのインターフェースでユーザーがどのように反応したのかを測定し、定期的に分析するのが重要です。

ここでは触れませんが、Google Analyticsを使って、適切な計測ポイントをいれておきましょう。

まとめ

Storyboardを切り替えるとアプリ全体のユーザーインターフェース全体を差し替えることができ、A/Bテストを実施できます。
また、 「User Defined Runtime Attributes」を使うことによって、データベースの変更やAPIの変更にも対応できる仕組みを作ることも可能です。

iOSでA/Bテストができるサービスもいくつかあるので、実装がめんどうであれば、そちらを利用してもいいと思います。テストをカスタマイズしたい場合や、自サーバーでデータを収集したい場合などには、是非この方法も試してみてください。