CloudKitの概念を整理してみた
iCloudによる安全で簡単に使えるスケーラブルなストレージ
Soudai Sasada
個人でiOSアプリを開発するにあたりある程度の規模のデータを格納したく色々と情報を漁っていたのですがその中でCloudKitについてよく分からない点が多く、日本語で自分が知りたかった情報を見つけることができなかったため自身の頭の整理を兼ねて記事にしてみました。
iCloud storage
CloudKitの説明に入る前にまずiCloudについておさらいをします。
iCloudはApppleが提供するオンラインストレージサービスです。ユーザーはiCloudにデータを保存することでバックアップや別端末との同期を取ることができます。バックアップは3つの種類があります。以下、こちらの記事からの抜粋です。
タイプ | 説明 |
---|---|
Key-value storage | アプリの設定や状態などを保存するためのKVS。最大容量は1アプリ1MB。 |
iCloud Documents | ファイルベースのストレージ(Core Data含む)。ドキュメントやドローファイル、または複雑なアプリの状態などを格納するために利用可能。最大保存容量はユーザーのiCloudアカウントに依存。 |
CloudKit storage | Appleが提供するBaaSの内のストレージ機能。構造化されたデータを管理したり、ユーザー同士で共有したいファイルやデータを保存したい際に利用する。データの管理にはデータベースが使用され、各レコードはKVSとして扱う。 |
この表から単にiCloudといっても様々な機能がありCloudKitはその中の一つだということが分かります。それではここから本題に移っていきたいと思います。
全体像
CloudKitの各概念の説明に入る前にまずざっくりとCloudKitの全体像について説明します。
CloudKitはその名の通りクラウド上にデータを保存できるAppleによるオンラインストレージサービスであるiCloud上でアプリが利用するデータを保存するためのツールでありサービスです。CloudKitでは役割ごとに領域が分かれていて上位の領域が下位の領域を内包しています。この領域内で扱うデータの種類やポリシーに応じて様々なオプションが用意されているため、開発者はそれらを用途に合わせて選択し組み合わせることでユーザーのニーズに合ったアプリ開発が可能となります。
各領域ごとの大まかな説明は次のとおりです。
領域 | 説明 |
---|---|
Container | 名前空間で隔てられた領域 |
Database | 利用可能なアクセスポリシーごとに隔てられた領域 |
Zone | Record(実データ)が保存される領域 |
iCloudの中にContainerという箱が無数にあり、それぞれのContainerの中にDatabaseが用意され、Database内のZoneにRecordが種類(Record Type)ごとに集まった状態で入っているというイメージです。
それではContainerから順に見ていきます。
Container
ContainerはiCloud内で名前空間ごとに隔てられた領域となりアプリは複数のContainerを利用することができます。Container名はどのような値でも設定できますが iCloud.\(バンドルID)
という命名が一般的のようです。もし複数のContainerを利用する場合には公式ドキュメントのように iCloud.\(バンドルID).\(役割A)
のようにネームスペースを切っていくのが良さそうです。
CloudKitの利用を開始するにはまずアプリでiCloudを利用するための準備が必要です。
XCodeでSigning & CapabilitiesにあるCapabilityの追加ボタンからメニューを開き、左のサイドメニュー内にあるiCloudを選択することでCloudKitを含むiCloudの機能を利用することができます。
iCloudが利用できるようになったら各機能の中からCloudKitにチェックを入れ、Containerの追加ボタンを押しましょう。ボタン押下時に立ち上がる入力欄ではContainer名だけ入力すれば自動で名前にプレフィックスが割り当てられるため iCloud.
というプレフィックスを自身で入力する必要はありません。
Database
DatabaseはContainer内でアクセスレベルによって分けられた領域となっており Public
、 Private
、 Shared
の3つに分かれます。
種類 | 読み込み | 書き込み | 書き込み先 |
---|---|---|---|
Public | 全ユーザー | iCloudユーザー | 共通領域 |
Private | iCloudユーザー | iCloudユーザー | ユーザー単位の領域 / 第三者アクセス不可(開発者含む) |
Shared | iCloudユーザー | iCloudユーザー | ユーザー単位の領域 / 第三者アクセス可 |
ここからはそれぞれのデータベースの特性を見ていきます。
Public database
Public databaseは全てのアプリユーザーがデータを読むことができるためiCloudの利用状況に関わらず共通のデータを使用したい場合に適しています。
iCloudにログインしているユーザーはPublic databaseに対し書き込みを行うことができますが、アプリ側で書き込むような機能を実装しなければアプリ開発者のみが(CloudKitのコンソールを通じて)書き込みすることができるためマスターデータを提供するようなことが可能です。
Private database
iCloudにログインしているユーザーが自身のプライベートな領域に読み書きをすることができます。Private databaseはiCloudにログインしているユーザーのみが読み書き可能でアプリ開発者含めた第三者はデータにアクセスすることができないためユーザーが安全にデータを格納するための領域を提供したい場合に適しています。
Shared database
Shared databaseはPrivate databaseと同じようにiCloudにログインしている場合にのみアクセスできユーザーのPrivate databaseのレコードをアプリケーションの他のユーザーと共有するために使用されます。他ユーザーへは読み込み、書き込み、その両方の権限を付与することができます。特定のユーザーのみ公開するようなことはできません。またデータの所有ユーザーが非公開化した場合は他ユーザーはアクセスできなくなります。
Zone
Zoneは CKZone
型のオブジェクトで表現されるデータの保存場所です。各DatabaseにそれぞれZoneが用意されており、実データとなるRecordはここに保存されます。全てのDatabaseにデフォルトのゾーンがありますが、プライベートデータベースのみカスタムゾーンとしてデフォルト以外に複数のZoneを作成することができます。
Security Role
アプリ開発者はSecurity RoleによってPublic databaseのRecordに対しRecord Typeごとにパーミッションを設定することができます。パーミッションは次のとおりです。
パーミッション | 説明 |
---|---|
Create | 作成 |
Read | 読み込み |
Write | 書き込み(更新) |
Security Roleはデフォルトで以下が用意されていてこれらは役割を持っており削除することはできません。また、これらは新たに作成されたRecord Typeにデフォルトで権限を付与します。それぞれの役割とデフォルトで付与される権限は次のとおりです。
名前 | 説明 | デフォルトの権限 |
---|---|---|
_world |
全てのユーザー | Read |
_icloud |
全てのiCloudユーザー | Create |
_creator |
Recordの作者 | Write |
Record Type
RecordはZoneの中でスキーマごとに一つの集合として表現されますがそのスキーマがRecord Typeとなります。Record Typeのフィールドは全てのRecordに予め用意されているメタデータと開発者が独自に設定可能なフィールドに分類されメタデータを変更することはできません。
フィールドは名前と型を持ち、また、フィールドごとに複数のIndexを設定することが可能です。
メタデータのフィールドは次のとおりです。
名前 | 型 | 説明 |
---|---|---|
createdTimestamp |
Date/Time | 作成日時 |
createdUserRecordName |
Reference | 作成ユーザーID |
___etag |
String | レコードの変更を検知するためのタグ |
modifiedTimestamp |
Date/Time | 最終更新日時 |
modifiedUserRecordName |
Reference | 最終更新ユーザーID |
recordName |
Reference | ID |
CloudKitではWebコンソール上にログインしている開発者含めた全ての利用者が Users
のRecordです。Recordにはそれぞれ recordName
と呼ばれるIDが存在し、createdUserRecordName
と modifiedUserRecordName
はそれぞれ作成、更新をしたユーザーの recordName
となっており、 Reference
型を使って特定のRecordに対し参照を持つ形で表現されています。
___etag
はCloudKit上のRecordを参照しているユーザーが当該Recordへの更新を検知するための値です。Recordをフェッチしたあとにこの値を見て現在参照しているRecordが古いかどうかを確認することができるようになっています。
Index
IndexはRecord TypeごとにRecordをまとめて取得するための仕組みです。Indexは用途によって種類が分かれており各フィールドに対しそれぞれの種類で1つずつ、最大で3つ設定することが可能で、設定可能なフィールドはメタデータを含む全てのフィールドです。
Indexの種類は次のとおりです。
種類 | 説明 |
---|---|
Queryable | 指定したフィールドで検索をできるようにします |
Searchable | 指定したフィールドを全文検索の対象とします |
Sortable | 指定したフィールドでソートをできるようにします |
特定のRecord Typeにおいて検索をするためにはQueryableがいずれか1つ以上のフィールドに設定されている必要があります。これはQueryableが検索をできるようにするためのIndexだからです。また、Queryableで設定したフィールドに対してはフィルタリングの条件指定ができるようになります。
recordName
にQueryableを設定した場合のみフィルタリングを設定せずに検索することができましたが、 recordName
にはQueryableを指定せずそれ以外のフィールドにQueryableを設定している場合は当該フィールドへのフィルタリングを設定しないと検索することができませんでした。このあたりはなぜなのかよく分かっていません。
Record
Recordは CKRecord
型のオブジェクトでRecord Typeで指定されたフィールドごとにキーと値のペアを持つ辞書のようなデータとなります。
CKRecordのドキュメントはこちらです。
Recordのフィールドに指定可能な型は次のとおりです。
CloudKitの型 | Swiftの型 | 説明 |
---|---|---|
Asset | CKAsset | 画像や動画、バイナリなどのデータ |
Bytes | NSData | 構造体など(バイナリなどの巨大なデータに使用するのは非推奨) |
Location | CLLocation | 緯度軽度などの位置情報 |
Double | NSNumber | 小数(64bit浮動小数点数) |
Int(64) | NSNumber | 整数(64bit符号付き整数) |
Reference | CKRecord.Reference | 別Recordとの関連 |
String | NSString | 文字列 |
Date/Time | NSDate | 日時 |
全ての型は配列とすることもできます(Assetの配列やLocationの配列など)。
暗号化
iCloudでは全てのデータがアカウントベースで暗号化されていますがさらに追加の保護レイヤーとしてReference以外の型はiCloudサーバ上で暗号化することができます。暗号化指定された型の値は書き込み時に自動で暗号化され読み込み時に複合化することができます。なおAssetはデフォルトで暗号化されるため指定する必要はありません。
例外としてReferenceのみiCloudサーバ上で見える必要があるため暗号化することができません。
CloudKitのセキュリティについてのドキュメントはこちらです。
Reference型
Referenceは特殊で他のRecordへのリンクを作成できRecord間で所有関係を持たせることができ、これにより所有する側のRecordを削除したときに所有される側のRecordを連鎖的に削除することが可能となります。リンクできるのは同一のZone内にあるRecordのみです。
Reference型についてのドキュメントはこちらです。
Subscription
Subscriptionはユーザーがデータの変更をリアルタイムで検知するための仕組みです。購読は種類によってDatabase、Record Zone、Queryの3つに分かれます。
購読の種類 | 利用可能なDatabase | 説明 |
---|---|---|
Database | Private / Shared | ゾーンごと購読したいがゾーン名が不明な場合に使用 |
Record Zone | Private | iCloudユーザー自身のカスタムゾーンを購読したい場合に使用 |
Query | Public / Private | クエリの結果を購読したい場合に使用 |
Subscriptionについてのドキュメントはこちらです。
まとめ
CloudKitの概念について自分が理解できるように整理してみましたが思った以上に骨が折れました。まだまだ理解できていない点が多いのでこれから実際に利用してみて理解を深めていこうと思います。