iCloudと共にCoreDataを使う方法

Appleのドキュメント
Using Core Data with iCloud Release Notes
を大まかに訳したものです。

アプリで生成されたデータをCoreDataで永続的に保存しつつ、
そのデータをiCloudで同期する方法を大まかに説明しています。


iCloudと共にCoreDataを使う

CoreDataとiCloudをAppで使う場合2つの選択肢が存在する。
A.どういったAppを作りたいか?
B.どういう型のストアを使いたいか?


A.どういったAppを作りたいか?

iCloudと統合するCoreData App は2種類ある。
Library-style App 単一の永続ストアを持ち、App全体から利用される。
例:Music and Photos.
Document-based applications Appのライフタイムの中で、異なるドキュメントを異なる時間に開くもの。
例:Keynote and Numbers
既にCoreDataを使っているなら、Library-style Appがあてはまるだろう。
この場合、Core DataのiCloud統合SQLiteのストアを使用することを勧める。

UIKitは、UIManagedDocumentクラス(UIDocumentのサブクラス)を提供し、iCloudを使ったDocument-based applicationsをサポートする。library-style applicationsの場合、iCloudを使っていない場合、一般的に Core Data stackをセットアップする。
どちらの場合でも、永続的なストアを設定する必要がある。


B.どういう型のストアを使いたいか?

目的に応じて、ストアタイプを選択する。
  1. SQLite
  2. Atomic (the binary store type)、もしくは NSAtomicStore由来のカスタムAtomic


Use the SQLite Store for Large Datasets and Fine-Grained Change Notification


効率的なper-record changeの伝播と、対応する変更通知を提供するので、SQLite storeを使う。

CoreDataはiCloudとSQLiteのstoreの効率的な統合をサポートする機能の強化を含む。
主な新機能は、あなたが永続ストアに対して行った各変更が、iCloudに格納されているdiscrete transaction log filesに記録されること。(iCloud上に直接永続ストアが維持されるのではない)
iCloudを介した伝達が効率的であることを意味する。(代わりに、変更ごとに全体のSQLiteファイルをプッシュする)
これには、いくつかの影響がある:


・ストアへの変更に関するtransaction logsを保存する場所は、コアデータに指示する必要がある。

storeを構成した時に、NSPersistentStoreUbiquitousContentNameKey、オプションでNSPersistentStoreUbiquitousContentURLKey に値を与える必要がある。
(NSPersistentStoreUbiquitousContentURLKeyを明示しない場合、URLは、application bundle identifierを、NSFileManagerのURLForUbiquityContainerIdentifier:メソッドに渡すことによって構築される。)
コンテンツ名は、異なるデバイス間でストアを識別するために使用される。そのため、transactionsはすべてのデバイス間の永続的ストアファイルの潜在的な多くのインスタンスで一貫して同期される。
このような理由から、それぞれのstoreに一意の名前を与えることを確認する必要がある。(例:UUID)


・iCloudからストアを削除するときは(どちらのデバイスにローカルにするために、または完全にそれを削除する)直接transaction logsを消さなければならない。

NSFileManagerを使ったコーディネート・オペレーションを行う。
カスタムまたはユニークなNSPersistentStoreUbiquitousContentURLKeyを指定しているのなら、
単にそのディレクトリを削除すると、ストアに関連付けられているすべてのトランザクションログデータが削除される。
NSPersistentStoreUbiquitousContentURLKeyを共有しているのなら、NSPersistentStoreUbiquitousContentNameKeyサブディレクトリを取り除けば良い。


・変更がiCloudによって伝播される場所で、SQLiteファイル自体を格納してはいけない。

これは、SQLiteストアファイルを含む全体の親ディレクトリが含まれている。
これは、アプリケーションの種類のコンテキストで後述。



Guidance for Library-style Applications


library style applicationにおいて、通常は単一の永続ストア及びコーディネータを持つ、単一のCoreDataスタックを保持する。

SQLiteストアを使う場合、
・addPersistentStoreWithType:configuration:URL:options:error: でストアを追加した時に
NSPersistentStoreUbiquitousContentNameKeyを、オプションでNSPersistentStoreUbiquitousContentURLKeyを提供する。
好きな名前を選択することができる contentURLは、しかしながら、ubiquity containerを識別する必要がある。
・ストア自体を、ローカルアプリケーションサンドボックス内、もしくは、ubiquity container内のa .nosync suffixディレクトリ内に配置する必要がある。
永続ストアによるNSPersistentStoreDidImportUbiquitousContentChangesNotification通知を観測できる。
これはレコード単位の変更に対応することができる。

atomicストアを使う場合、
ubiquity containerに直接、永続ストアを配置できる。iCloudから伝播された変更を処理するには、適切なNSFilePresenterプロトコルのメソッドを実装する。



スキーマの移行


コア·データ·アプリケーションは、異なるスキーマを使用した他のバージョンとは同期しない。SQLiteストアを使った場合、CoreDataはiCloudにおいて、軽量の移行だけをサポートする。
軽量の移行を使った時、Appの違うバージョン同士では、互いに同期されないだろう。しかし、古いバージョンをアップグレードした時、古いバージョンはそれまでの変更を拾い、新しいバージョンは古いバージョンの変更を統合するだろう。

アトミックストアはファイル全体を上書きするため、スキーマを更新する場合、ストアは、以前のスキーマを使用しているクライアントで読み取ることができない。




機能制限


iCloudを使う際に、SQLiteストアはいくつか制限される。こういうときに:

・順序付けられた関係はサポートされない。
・パッケージ化されたデータベースファイルを使用して初期コンテンツをシードするべきではない。代わりに、コードを書いてデフォルトアイテムを作るか、NSPersistentStoreCoordinatorのmigratePersistentStore:toURL:options:withType:error:メソッドを使ってパッケージ化されたデータベースを必要な場所に統合することができる。
・mapping modelsを使ったスキーマ移行はサポートされない。軽量の移行はサポートする。