[iOS 8] App Extension #3 – App Group で containing app とデータを共有する

App Group

App Group は iOS 8 の新機能で、同一デベロッパーがリリースしたアプリ間でデータの格納領域を共有することができます。App Group で共有されるデータの格納領域は、App Group に所属する個々のアプリのサンドボックスとは別となっており、独立したローカルストレージ領域が割り当てられます。App Group に所属するアプリは、そのローカルストレージの領域に対してデータの永続化を行うことによってデータを共有します。

ローカルストレージ内には任意のファイルを書き込むことができるため、SQLite のファイルを作成して DB を共有することもできます。UserDefaults に関しても独立した領域が割り当てられ、設定等の情報を共有することができます。

App Group によって定義される共有領域のことを shared container と言います。個々の shared container は Bundle Identifier のような識別子によって管理されます。

App Group と App Extension

App Extension はその性格上、containing app とデータを共有したいというケースが非常に多いと思います。しかし、containing app と Extension は別のサンドボックスが割り当てられるため、通常は Keychain 等を利用しないとデータの共有ができません。App Group は cotaining app と Extension の間でも有効であるため、この仕組みを利用してデータを共有することができます。

App Group の設定方法

今回は、App Extension とその containing app の間でデータを共有するケースを例に、App Group の設定方法を見てきたいと思います。Xcode でプロジェクトを作成し、containing app と Extension のターゲットが既に追加されているものとします。

Xcode への iOS Developer Program アカウントの追加

ここからの操作は、iOS Developer Program に登録されたアカウントで Certificates, Identifiers & Profiles のページに対して編集を行うのと同等のことを Xcode が自動的に実行します。このため、Certificates, Identifiers & Profiles ページに対して編集権限を持つアカウントを事前に Xcode に登録しておいて下さい。Xcode へのアカウントの追加は、Xcode の Preferences ウィンドウ内の Accounts タブから行うことができます。

ios-appgroup_009

App Group の有効化

データを共有したい containing app や Extension は個別に App Group を設定する必要があります。まずは、containing app の設定を行います。

App Group の設定は、ターゲットの Capabilities で行います。containing app のターゲットを選択して、Capabilities タブを選択して下さい。その中に App Groups というカテゴリがありますので、スイッチを ON にして有効化して下さい。

ios-appgroup_001

すると、どの Development Team を対象にするかを選択するダイアログが表示されますので、containing app と Extension をリリースしたい Development Team を選択して Choose をクリックして下さい。

ios-appgroup_002

Capabilities の画面に戻ります。App Group のカテゴリ内に、Development Team に対して登録済みの App Group のリストが表示されます。下図では、先程選択した Development Team に App Group が登録されていないため、リストは空になっています。

ios-appgroup_003

App Group の作成

登録済み App Group リストの左下に App Group を追加する + ボタンがありますので、それをクリックします。

ios-appgroup_004

App Group の識別子を入力するダイアログが表示されます。App Group の識別子は group. で始まる必要があります。group. の後ろは、Bundle Identifier と同じように逆ドメインを指定するようにしましょう。識別子を入力したら OK をクリックします。

ios-appgroup_005

Capabilities の画面に戻ると、登録済み App Group リストに先程追加した App Group の識別子が追加されているのが確認できます。

ios-appgroup_006

追加した App Group を iOS Developer Center で確認してみましょう。Certificates, Identifiers & Profiles のページ内に App Groups という項目があります。App Group を作成したアカウントでログインして App Groups を選択すると、一覧に作成した App Group が追加されているのが確認できます。

ios-appgroup_007

これで containing app 側の App Group の設定は完了しました。Extension にも先程作成した App Group の設定を追加します。

ios-appgroup_008

以上で、containing app と Extension は同じ App Group に所属し、共に App Group で定義された shared container にアクセスできるようになります。

shared container の利用方法

ローカルストレージ

ローカルストレージへのアクセスを行う際には、NSFileManager を利用して shared container による共有ディレクトリへのパスを取得します。group.jp.classmethod.SampleAppGroup という識別子を持った App Group の場合、下記のようなコードになります。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *destURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"group.jp.classmethod.SampleAppGroup"];

上記の destURL は共有ディレクトリのルートパスを指す NSURL となります。

User Defaults

User Defaults へのアクセスを行う際には、通常の場合と同じく NSUserDefaults を利用します。ただし、NSUserDefaults のインスタンスを生成する際に、standardUserDefaults コンビニエンスコンストラクタではなく、initWithSuiteName: イニシャライザを利用します。イニシャライザの引数には App Group の識別子を渡します。

group.jp.classmethod.SampleAppGroup という識別子を持った App Group の場合、下記のようなコードになります。

NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.jp.classmethod.SampleAppGroup"];

NSUserDefaults のインスタンスを取得してからの利用方法は、App Group でない場合と同じです。

まとめ

App Group を利用することによって、何かと面倒なアプリ間のローカルでのデータ共有を簡単に行うことができるようになりました。特に Extension を作る際には積極的に利用したいですね。