iCloud に環境設定を保存
アプリは、iCloud のキー値保管を使用して、ユーザーの他のコンピュータや iOS デバイス上の他のインスタンスと少量のデータを共有できます。キー値保管は、環境設定に使用するような単純なデータ型を対象としています。たとえば、雑誌アプリは、ユーザーが読んでいる現在の出版物とページ番号を保存して、起動時にアプリの別のインスタンスが同じページを開くことができます。大量のデータや複雑なデータ型には使用しないでください。
iCloud の キー値保管を使用するには、以下の操作を行います。
- Xcode で、アプリの com.apple.developer.ubiquity-kvstore-identifier 資格を構成します。
- コードで、共有された NSUbiquitousKeyValueStore オブジェクトを作成し、変更通知を登録します。
- 値を取得および設定するには、NSUbiquitousKeyValueStore のメソッドを使用して下さい。
iCloud のキー値データは、単純なプロパティリスト型 (文字列、数値、日付など) に限られます。
iCloud キー値保管を使用するための戦略
キー値保管は、大量のデータを格納するためのものではありません。これは、構成データ、環境設定、および少量のアプリ関連データを保管するためのものです。キー値保管がニーズに適しているかどうかを判断するには、以下の点を考慮してください。
- 各アプリは、キー値保管内の合計 1 MB 容量に制限されています。(また、キーごとに 1 MBの制限があり、最大 1024 のキーが使用できます)。したがって、大量のデータを共有するためにキー値保管を使用することはできません。
- キー値保管は、プロパティリスト型のみをサポートしています。プロパティリスト型には、NSNumber、NSString、および NSDate などの単純な型があります。また、NSData オブジェクトに生データブロックを保管し、NSArray と NSDictionary オブジェクトを使用してすべての型を整理することもできます。
- キー値保管は、滅多に変更されないデータを保管するためのものです。デバイス上のアプリがキー値保管に頻繁に変更を加えると、システムはサーバーへの見回り回数を最小限に抑えるために、いくつかの変更の同期を遅延させるかも知れません。アプリの変更頻度が高いほど、後の変更は延期され、すぐに他の端末に表示されなくなる可能性が高くなります。
- キー値保管は、同じデータを保存するための環境設定やその他のローカルな手法に代わるものではありません。キー値保管の目的は、アプリ間でデータを共有することですが、iCloud が有効になっていないか、特定のデバイスで利用できない場合でも、データのローカルコピーを保持することもできます。
キー値保管を使用して環境設定を共有する場合、1 つの方法は、ユーザーのデフォルトデータベースに実際の値を格納し、キー値保管を使用してそれらを同期させることです。(環境設定システムを使用したくない場合は、カスタムプロパティリストファイルや他のローカルな記憶装置に変更を保存することもできます)。キー値をローカルで変更する場合は、その変更をユーザーのデフォルトデータベースと iCloud キー値保管に同時に変更を書き込みできます。外部ソースから変更を受け取るには、通知 NSUbiquitousKeyValueStoreDidChangeExternallyNotification の監視者を追加し、あなたのハンドラメソッドを使用して外部から変更されたのはどのキーかを検出し、ユーザのデフォルトデータベース内の対応するデータを更新します。これにより、ユーザーのデフォルトデータベースには常に正しい構成値が含まれます。iCloud のキー値保管は、ユーザーのデフォルトデータベースに最新の変更があることを保証するためのメカニズムになります。
アプリを構成してキー値保管を使用
キー値保管を使用するには、com.apple.developer.ubiquity-kvstore-identifier 資格を使用してアプリを明示的に構成する必要があります。App Distribution ガイド (アプリ配布ガイド) の iCloud サポートの追加 で説明したように、Xcode を使用してこの資格を有効にし、アプリの値を指定して下さい。
キー値保管を有効にすると、アプリのバンドル ID に基づいてコンテナフィールドのデフォルト値が Xcode によって自動的に設定されます。ほとんどのアプリでは、デフォルト値が必要です。ただし、アプリが別のアプリとキー値保管を共有する場合は、代わりに他のアプリのバンドル ID を指定しなければなりません。たとえば、アプリのライト (lite) 版をお持ちの場合は、有料版と同じキー値保管を使用したいかもしれません。
資格を有効にすることは、共有した NSUbiquitousKeyValueStore オブジェクトを使用するためにしなければならない作業です。資格が構成され、有効な値を含む限り、キー値保管オブジェクトは、そのデータをユーザーの iCloud アカウント内の適切な場所に書き込みます。指定した iCloud コンテナに接続するときに問題が発生すると、キー値の読み取りまたは書き込みの試行は失敗します。キー値保管が正しく構成されアクセス可能であると保証するには、アプリの起動サイクルの早い段階で以下のようなコードを実行する必要があります。
NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateKVStoreItems:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:store]; [store synchronize];
アプリの起動サイクルの早い段階でキー値保管オブジェクトを作成することをお勧めします。これは、アプリが iCloud からの更新を適時受け取ることを保証するためです。キー値が変更されたかどうかを判断する最良の方法は、通知 NSUbiquitousKeyValueStoreDidChangeExternallyNotification に登録することです。また、起動時には、手動で synchronize メソッドを呼び出して、外部で変更があったかどうかを検出する必要があります。アプリの実行中に他の時そのメソッドを呼び出す必要はありません。
iOS アプリの資格の構成方法の詳細については、アプリ配布ガイド 内の「機能の追加」をご覧ください。
キー値保管値へのアクセス
キー値保管値は、NSUbiquitousKeyValueStore クラスのメソッドを使用して取得および設定して下さい。このクラスには、ブール型、long long、および double のスカラー値を持つ環境設定を取得および設定するためのメソッドがあります。NSData、NSDate、NSString、NSNumber、NSArray、または NSDictionary オブジェクトが値であるキーを取得および設定するメソッドもあります。
ローカルに保管された環境設定を更新する方法としてキー値保管を使用している場合は、リスト 3-1 のコードと同様のコードを使用して、ユーザーのデフォルトデータベースへの更新を調整できます。この例では、iCloud とユーザーのデフォルトデータベースの両方で同じキー名と対応する値を使用することを前提としています。また、通知 NSUbiquitousKeyValueStoreDidChangeExternallyNotification に応答して呼び出すメソッドとして以前に updateKVStoreItems: メソッドを登録したことを前提としています。
リスト 3-1 iCloud を使用してローカルの環境設定値の更新
- (void)updateKVStoreItems:(NSNotification*)notification { // Get the list of keys that changed. NSDictionary* userInfo = [notification userInfo]; NSNumber* reasonForChange = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey]; NSInteger reason = -1; // If a reason could not be determined, do not update anything. if (!reasonForChange) return; // Update only for changes from the server. reason = [reasonForChange integerValue]; if ((reason == NSUbiquitousKeyValueStoreServerChange) || (reason == NSUbiquitousKeyValueStoreInitialSyncChange)) { // If something is changing externally, get the changes // and update the corresponding keys locally. NSArray* changedKeys = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]; NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore]; NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; // This loop assumes you are using the same key names in both // the user defaults database and the iCloud key-value store for (NSString* key in changedKeys) { id value = [store objectForKey:key]; [userDefaults setObject:value forKey:key]; } } }
キー値保管変更の範囲の定義
NSUbiquitousKeyValueStore メソッドのいずれか 1 つへの呼び出しはすべて、単一の微細な処理として扱われます。その処理のデータを iCloud に転送すると、処理全体が失敗するか、成功します。成功すると、すべてのキーが保管庫に書き込まれ、失敗した場合はキーは書き込まれません。保管庫へのキーの部分書込みはありません。障害が発生すると、システムはまた、障害の理由を含む NSUbiquitousKeyValueStoreDidChangeExternallyNotification 通知を生成します。キー値保管を使用している場合は、その通知を使用して問題の可能性を検出する必要があります。
有効にするために値をすべて同時に更新する必要があるキーのグループがある場合は、それらを 1 つの処理で一緒に保存します。1 つの処理で複数のキーと値を書き込むには、すべてのキーと値を含む NSDictionary オブジェクトを作成します。次に、setDictionary:forKey: メソッドを使用して、キー値保管に辞書オブジェクトを書き込みます。変更の辞書全体を書き込むことで、すべてのキーが書き込まれるか、まったく書き込まれないことが保証されます。