単一の真実の源:SwiftData、MCP、iCloud
Get Bananasには、同じ買い物リストに書き込める3つの呼び出し元があります。iOSアプリで行をタップする人間。SiriのリクエストをAppIntent経由でルーティングするApple Intelligence。stdio経由でMCPツールを呼び出すClaude Codeセッション。ユーザーの頭の中ではリストは1つの正典的な存在ですが、問題はそれがストレージのどこに住んでいて、意見が食い違ったときにどの呼び出し元が勝つのかという点です。
統合記事では、iOSアプリの3つのサーフェスを挙げました。人間、Apple Intelligence、エージェントです。各サーフェスは同じドメイン状態を読み書きする必要があります。この要求こそが、多すぎるアプリで出荷されているアーキテクチャ上の誤りを生み出します。各サーフェスが独自のストアを持ち、サーフェス同士がドリフトし、最後に触れたサーフェスによってユーザーは3つの異なるバージョンのリストを目にすることになるのです。生き残るパターンは、サーフェスと基盤の間に明示的な同期パスを持つ、単一の真実の源です。
この記事では、基盤の選択肢、それぞれが強制する競合解決ルール、そして3つの呼び出し元クラスすべてが書き込み可能な場合に持ちこたえるアーキテクチャを名指しで挙げます。説明にはGet Bananasの実際のレイアウトを使います。アプリ内状態にはSwiftData、プロセス間同期にはiCloud Drive上のJSONファイル、iOSサンドボックスの外側から同じファイルを読み書きするMCPサーバーです。1
TL;DR
- 3つの基盤を組み合わせます:SwiftData(プロセス内、高速、スキーマ型付け)、iCloud Drive(プロセス間、ファイルベース、同期可能)、
NSUbiquitousKeyValueStore(デバイス間、キーバリュー、小さなペイロード専用)。 - ドメインごとにどの基盤が真実の源かを選びます。競合解決はその選択の必然的な結果であり、別問題ではありません。
- 3つのサーフェス(人間、Apple Intelligence、エージェント)は、それぞれドメイン層を介して基盤とやり取りします。競合解決ポリシーが宿るのはドメイン層です。
- 変更可能な全エンティティに付ける
lastModifiedタイムスタンプは、安価な競合解決プリミティブです。「最後の書き手が勝つ」は安価なポリシーです。より強い保証が必要なアプリは、明示的なマージロジックでその対価を支払います。 - アプリプロセス外のMCPサーバーはSwiftDataを読めません。橋渡しはシリアライゼーション層(iCloud Drive上のJSONファイル、App Groupコンテナなど)であり、アプリ内のSwiftDataリーダーとプロセス外のMCPサーバーの両方が話せる相手です。
3つの基盤
Appleは出荷済みのiOSアプリに対し、プロセス間およびデバイス間のパターンに登場する3つのネイティブな永続化基盤を提供しています。それぞれに固有の形があり、計画なしに混ぜるとドリフト問題が生じます。
SwiftData。 Core Dataに支えられたプロセス内永続化ストレージです。2 高速、スキーマ型付け、@Queryで問い合わせ可能、SwiftUIの観測システムと統合されています。ストアはアプリプロセスが所有します。アプリ拡張機能(ウィジェット、インテント、共有拡張機能)は、明示的な設定によりApp Group経由でSwiftDataコンテナを共有できます。アプリの署名コンテキスト外の開発者マシンで動作する任意の外部MCPプロセスは、SwiftDataコンテナへ安全にアクセスすることはできません。行はPersistentIdentifier(プロセス内)または@Attribute(.unique)の自然キー(プロセス間、デバイス間)を介してアドレス指定可能です。マイグレーションはVersionedSchemaとMigrationPlanを介して宣言的に行います(SwiftDataの本当のコストはスキーマ規律で扱っています)。
iCloud Drive。 ファイルベースのデバイス間同期で、ユーザーのiCloudコンテナ内のFileManager URL経由で表面化します。3 ファイルはユーザーがサインインしているすべてのデバイスに表示されます。競合解決はファイルレベルです。iCloudは並行編集の追跡にNSFileVersionを使い、アプリは競合ログを読んで何を残すかを決定します。iCloud Drive上のファイルはiOSアプリプロセスの外からアドレス指定可能です。MacのMCPサーバーは、iOSアプリが読むのと同じJSONファイルを開けます。Get BananasのMCP統合を機能させているのは、この基盤です。
NSUbiquitousKeyValueStore。 デバイス間のキーバリューストレージです。Appleの現在の公式上限はアプリあたり合計1MB、値あたり1MB、1024キー、キーあたり128 UTF-16文字、書き込みレートはスロットルされています。4 競合解決は組み込みです。システムが書き込みをシリアライズし、変更時にすべてのデバイスに通知します。小さく低頻度の状態(設定、最後に選択されたタブ、整数カウンター)に適しており、書き込みレートが高いデータや、スロットルがボトルネックとなるワークロードには不向きです。Returnはデバイス間のタイマー状態(ユーザーがiPhoneでタイマーを開始し、Apple Watchで確認する)にこれを使っています。5つのAppleプラットフォーム、3つの共有ファイルで扱っています。
4つ目の基盤、CloudKitは、いかにも候補に見えるものの、本クラスタのアプリがプロセス間MCP統合のために明示的に却下した選択肢です。CloudKitは競合認識レコードによる強力なデバイス間同期を提供し、Appleは非Apple環境がパブリックおよびプライベートのCloudKitデータベースと対話するためのCloudKit JSとCloudKit Web Servicesを実際に出荷しています。正直なトレードオフは統合コストであって不可能性ではありません。プライベートCloudKitデータベースに到達するNode.js製MCPサーバーは、CloudKit Web Servicesの認証、スキーマ定義、リクエスト署名を組み立てる必要があり、これは「JSONファイルを開く」ことに比べればかなりのエンジニアリング作業です。Get BananasがiCloud DriveとJSONファイルを選んだのは、MCPサーバーがNode.jsプロセスでありiOSアプリが見るのと同じデータを読み書きする必要があり、通常のファイルI/Oが最も抵抗の少ない経路だからです。1
決定:どの基盤が真実を保持するか
問題はどの基盤を使うかではありません。問題はどの基盤がどのドメインの真実の源かです。他の基盤はそれをキャッシュするか、ミラーするか、邪魔にならないようにします。
クラスタアプリで本番環境に耐えてきた決定マトリクスは次の通りです。
| ドメインの形 | 真実の源 | 理由 |
|---|---|---|
| 設定、環境設定、シンプルなフラグ | NSUbiquitousKeyValueStore |
デバイス間同期が自動。衝突はシリアライズされる。小さなペイロードで収まる |
| デバイスごとの一時状態 | UserDefaults(同期なし) |
デバイスローカル。別デバイスでの新規インストールを越えて存続すべきではない |
| プロセス内の問い合わせ可能なコレクション | SwiftData | 高速な@Query、SwiftUIの観測、スキーマ型付け。プロセス内のみ |
| 外部プロセスに到達する必要のあるプロセス内コレクション | iCloud Drive上のJSONファイル(ディスクへエクスポート) | iOSのSwiftDataリーダーと外部MCPサーバーの両方がファイルを読める |
| ユーザーごとの大きなコンテンツ(写真、音声、ドキュメント) | iCloud Drive(ファイル単位) | ユーザーのiCloudが自然なストア。CloudKitはより豊かな同期のために上に重ねられる |
| デバイス間のセッションレベル状態(iPhoneで動くタイマーをWatchで表示) | NSUbiquitousKeyValueStore |
サイズエンベロープに収まる。デバイス間プッシュのセマンティクスが必要 |
この決定が競合解決ポリシーを形作ります。ローカルアプリと外部MCPの橋渡しに関して、SwiftDataはプロセス間に固有の競合解決を持ちません。2つの呼び出し元が同じ行に書き込んだ場合、最後のtry context.save()が勝ちます。CloudKitに支えられパーシステント履歴を使うSwiftDataは、より豊かなデバイス間セマンティクスを担えますが、その表面はiOS側であり、外部のNode.js MCPケースには役立ちません。iCloud Driveは競合をNSFileVersionエントリとして表面化させます。アプリはそれらを歩いて勝者を選ばねばなりません。NSUbiquitousKeyValueStoreには値レベルでの競合解決が組み込まれています。
Get Bananasのアーキテクチャ
Get Bananasの実際のレイアウトです。
┌────────────────────────────────────┐
│ User's mental model │
│ "my shopping list" │
└─────────────────┬──────────────────┘
│
┌────────────┴───────────┐
│ │
┌───────▼────────┐ ┌───────▼─────────┐
│ iOS app │ │ MCP server │
│ (Get Bananas) │ │ (Node.js) │
└───────┬────────┘ └───────┬─────────┘
│ │
┌───────────┴────────┐ │
│ │ │
┌──────▼──────┐ ┌────────▼──────────┐ │
│ SwiftData │ │ iCloud Drive │◀──┘
│ (in-process) │◀──▶│ shopping_list. │
│ │ │ json │
└──────────────┘ └───────────────────┘
In-app reads/writes flow through SwiftData.
Cross-process reads/writes flow through the JSON file.
An iCloud sync layer (iCloudBackupManager) reconciles the two.
このアーキテクチャには3つのルールがあります。
SwiftDataはプロセス内クエリの真実の源である。 iOSアプリは、すべてのUIレンダリング、すべての@Queryに支えられたリスト、すべての検索でSwiftDataから読み込みます。書き込みはまずSwiftDataを通過します。モデルコンテキストが保存し、SwiftUIが再描画します。
JSONファイルはプロセス間状態の真実の源である。 iOSアプリがSwiftDataに保存するたびに、iCloudバックアップマネージャーが現在の状態をユーザーのiCloud Driveコンテナ内のJSONファイルにエクスポートします。MCPサーバーが書き込むときは、同じJSONファイルに書き込みます。ファイルが橋渡しです。
同期パスはiOSアプリ起動時とプロセス間書き込み後ごとに走る。 現在本番で稼働している同期ロジック(SyncManager.applyExport)は、各パスでJSONバックアップを正本として扱います。JSONファイルを読み、各行をUUIDでSwiftDataにマッチングさせ、既存の行をバックアップの値で上書きし、バックアップにあってSwiftDataにない行を追加し、SwiftDataにあってバックアップにない行を削除します(空のバックアップファイルがローカルデータベースを消去しないよう、破損ガードを設けています)。ポリシーは同期時にバックアップが勝つであって、タイムスタンプによる行ごとの最後の書き手勝利ではありません。iOSアプリが保存ごとに再エクスポートすることと組み合わさり、定常状態への収束は実用上速いものです。最後に書き込んだプロセスが、次の同期が読むJSONを生成するからです。
このアーキテクチャはプロセス間の到達範囲のために複雑性を引き受けています。純粋なSwiftDataアプリにはこれらは何も必要ありません。MCPサーバーのないアプリにはJSON橋渡しは必要ありません。デバイス間同期のないアプリには調停器は必要ありません。Get Bananasがこれら3つすべてを必要とするのは、3つの呼び出し元クラス(iOS経由の人間、iOS上のApp Intents経由のApple Intelligence、Mac開発者マシンからのMCP経由のエージェント)すべてが同じ買い物リストに触れるからです。
アップグレードパス:行ごとの最後の書き手勝利
「同期時にバックアップが勝つ」という出荷中ポリシーは安価で、シングルユーザー、一度に1人のアクティブな書き手というケースで機能します。iOSアプリとMCPサーバーがJSONファイルに連続して書き込む場合に苦戦します。最後に書き込んだプロセスが、実際には競合していなかった行についても他方の変更を上書きしてしまうのです。今日の緩和策は、iOSアプリがSwiftData保存ごとに再エクスポートすることで、JSONファイルを最新のアプリ内状態にほぼ揃え続けることです。定常状態は問題ありません。真に並行なケースでは作業が失われ得ます。
最も安価なアップグレードは、lastModified: Date?カラムをキーとした行ごとの最後の書き手勝利です。ShoppingItemモデルはマイグレーション安全のためにすでにこのフィールドを持っています(SwiftDataの本当のコストはスキーマ規律で扱っています)が、JSONエクスポートもMCPサーバーも現状ではこれをシリアライズしたり尊重したりしていません。lastModifiedをエクスポートとapplyExportに通すと、マージポリシーが「バックアップが勝つ」から「新しい行が勝つ」に変わります。
- 両側に値があり、片方がより新しい。 最も新しい方が勝つ。もう一方の行が更新される。
- 両側に値があり、同点。 主キーで決着、またはサーフェスで決着(iOSアプリが同点で勝つことで、ユーザーの最新のアプリ内操作を優先する)。
- 片側にのみ値がある。 値のある側が勝つ。
- どちらにも値がない。 どちらの行も
lastModified時代以前のデータ。調停器が次回のためにDate()を刻印する。
このポリシーは安価で、推論しやすく、おおよそ1%のケース(同じ行の異なるフィールドへの並行編集)で間違っています。買い物リストにとって1%は問題になりません。ドキュメントエディタにとっては絶対に問題になります。より強い保証が必要なアプリは、このベースの上にフィールドレベルマージ、CRDT、または操作変換を重ねます。Get Bananasはまだその複雑さを必要としていません。だからこそ、行ごとのLWWはロードマップにあり、より豊かなマージはありません。
3つの呼び出し元クラスと基盤
3つのサーフェスからの呼び出し元クラスを基盤の決定にマッピングします。
人間サーフェスはSwiftData経由で書き込む。 iOSアプリでチェックボックスをタップしたユーザーは、SwiftUI層を通じてドメイン関数に発火し、その関数がSwiftData行を変異させ、モデルにlastModified = Date()を刻印し、モデルコンテキストを保存します。iCloudエクスポートが現在の状態をJSONファイルに書き込みます。MCPサーバーは次回の読み取り時に新しい状態を取得します。
Apple IntelligenceサーフェスはSwiftData経由で書き込む。 Siri経由で起動されたAppIntentはiOSアプリプロセス内で動作し、人間サーフェスが使うのと同じドメイン関数に到達します。SwiftData状態が変異し、モデルのlastModifiedが更新され、JSONエクスポートが新しい状態をキャプチャします。
エージェントサーフェスはJSONファイル経由で書き込む。 Mac上のClaude CodeセッションからのMCPツール呼び出しは、JSONファイルを直接変異させます(iOSアプリからの並行書き込みを処理するためファイルロック付きで)。次にiOSアプリが起動または同期するとき、SyncManager.applyExportがファイルを読み、UUIDで項目を歩き、両側に存在する行をバックアップの値で更新し、バックアップにある行を追加し、バックアップが省略している行を削除します(空バックアップガード付き)。出荷中ポリシーは同期時にバックアップが勝つです。アップグレードパスはJSONにlastModifiedを加え、ポリシーを新しい行が勝つへシフトできるようにします。
非対称性は実在し、意図的なものです。人間とApple Intelligenceの両サーフェスはiOSアプリプロセス内で動作し、SwiftDataをネイティブに使います。エージェントサーフェスはiOSアプリプロセスの外で動作し、それが到達できる基盤だからこそJSONファイルを使います。両半分をまとめているのは調停器です。
このパターンが間違った答えである場合
JSON橋渡しパターンが間違っているケースをいくつか挙げます。
書き込みレートの高いデータ。 1秒あたり多数の編集を行うライブドキュメントエディタは、毎回の書き込みでコレクション全体をJSONファイルにシリアライズするコストを支払えません。正解は、実バックエンドに対する操作変換またはCRDTです。
強い一貫性要件。 金融取引の元帳はJSONファイル上の最後の書き手勝利を許容できません。正解は、明示的なトランザクションセマンティクスを持つCloudKit(あるいはサーバーサイドデータベース)です。
ユーザー同士がリアルタイムでお互いの編集を見るマルチユーザーコラボレーション。 iCloud Drive同期は結果整合的であって、リアルタイムではありません。一方のデバイスでアプリを閉じ、別のデバイスで開くユーザーは同期した状態を見ます。別のユーザーのカーソルがドキュメントを横切るのを見ているユーザーは、それを目にできません。正解は、リアルタイムコラボレーションフレームワーク(yjs、automerge、またはカスタムWebSocket層)です。
エージェントとユーザーが異なる識別子であるケース。 Get Bananasのパターンは、エージェント(MCP呼び出し元)と人間ユーザー(iOSアプリユーザー)が同じ人物であり、プロセスを跨いで操作しているだけだと仮定しています。エージェントが異なる識別子(共有リスト、管理者、自動ボット)の代わりに動作している場合、ユーザーのiCloud Drive上のJSONファイルは間違った基盤です。明示的な認証を持つマルチユーザー永続化が必要です。
このパターンはシングルユーザー、結果整合、プロセス間ケースに合います。MCP統合を持つ多くのアプリはまさにそのケースですが、そうでないアプリもあります。
異なる作り方をするとしたら
クラスタのアプリが出荷したか、出荷していればよかったと思っているパターンを3つ挙げます。
JSONシリアライゼーションを暗黙ではなく明示的にする。 Get Bananasの初版は、すべてのSwiftData書き込みをセーブフックでJSONにエクスポートしていました。第2版では、状態が安定したときにアプリが呼び出す明示的なステップにエクスポートを変えました。この変更により冗長な書き込みが減り、プロセス間状態がいつ公開されたかが明確になりました。すべての変異で暗黙的に保存するフックは、些末でないコレクションには過剰なI/Oを生み出します。
JSONファイルのスキーマをバージョン管理する。 JSONファイルはSwiftDataのVersionedSchemaとは独立した独自のスキーマを持ちます。SwiftDataスキーマが変わるとき(たとえばフィールドを追加するとき)、JSONシリアライゼーションも追従しなければなりません。安価な対処は、JSONの先頭にschemaVersion: Intフィールドを置くことです。調停器がそれを読み、正しい解釈を適用します。バージョニングがなければ、古いMCPサーバーが書いたv1のJSONファイルを読むv2のiOSアプリが、サイレントにデータ破損を起こします。
JSONをファイルロックする、調整を仮定しない。 iOSアプリとMCPサーバーは両方ともJSONファイルに書き込みます。NSFileCoordinator(プロセス内、iOS側)と(プロセス外、開発者マシン上の)ファイルロックなしでは、並行書き込みが破損ファイルを生み得ます。Get BananasのMCPサーバーはJSONに対してflockスタイルのファイルロックを使います。iOSアプリは書き込みにNSFileCoordinatorを使います。ファイルが実際に競合することは稀ですが、安全ベルトは安価です。
このパターンがiOS 26+で出荷するアプリにとって意味すること
3つの要点です。
-
ドメインごとに1つの真実の源を選ぶ。他の基盤はキャッシュ、ミラー、あるいは邪魔をしないようにする。 プロセス内クエリにはSwiftData、プロセス間橋渡しにはiCloud Drive上のJSON、小さなデバイス間状態には
NSUbiquitousKeyValueStore。競合解決はその選択の下流の結果です。 -
lastModifiedプラス最後の書き手勝利は安価なベースケース。 多くのアプリはより強い保証を必要としません。フィールドレベルのマージやCRDTを必要とする1%のケースは高価です。データの形が要求するまでそのコストを払うべきではありません。 -
調停器こそ荷重を担う部品。 SwiftDataとJSONファイルが食い違うとき、決めるのは調停器です。調停器はアプリ起動時、プロセス間書き込み後、iCloud同期イベント後に走ります。ルールはシンプルです。規律とは実際にそれを走らせることです。
Apple Ecosystemクラスタの全体像はこうです。Apple Intelligenceサーフェスのための型付きApp Intents、エージェントサーフェスのためのMCPサーバー、両者の間のルーティング問題、アプリ内オンデバイスLLM機能のためのFoundation Models、ランタイム対ツーリングLLMの区別、iOSアプリの3つのサーフェスの統合、iOSロック画面の状態機械のためのLive Activities、Apple Watch上のwatchOSランタイム契約、人間サーフェスの基盤としてのSwiftUIの内部、visionOSシーンのためのRealityKitの空間メンタルモデル、永続化のためのSwiftDataスキーマ規律、視覚層のためのLiquid Glassパターン、デバイス間到達のためのマルチプラットフォーム出荷。ハブはApple Ecosystem シリーズにあります。より広いiOSとAIエージェントの文脈については、iOS Agent Developmentガイドをご覧ください。
FAQ
なぜプロセス間同期にCloudKitを使わないのか?
CloudKitは競合認識レコードによる強力なデバイス間同期を提供し、AppleのCloudKit JS / CloudKit Web Servicesは非Appleスタックがプライベートなk CloudKitデータベースに到達することを実際に可能にします。制約は統合コストです。CloudKitを使うNode.js MCPサーバーは、CloudKitの認証(サーバー間キーまたはユーザーレベルトークン)、スキーマ宣言、署名済みリクエストを処理しなければなりません。iCloud DriveにJSONファイルを加えたものは通常のファイルI/Oであり、これが万能の翻訳器です。CloudKitが正解になるのは、チームが統合コストを支払う気があり、CloudKitのより強い同期と競合セマンティクスを欲しているときです。JSON橋渡しが正解になるのは、データの形に「ファイルを開く」で十分なときです。
2つの呼び出し元が同時に書き込んだとき、競合をどう扱うのか?
Get Bananasの出荷中ポリシーは「同期時にバックアップが勝つ」です。SyncManager.applyExportがUUIDで項目を歩き、ローカル行をバックアップから上書きし、空のバックアップが良好なローカルデータを消去しないようガードします。アップグレードパスはlastModifiedをキーとした行ごとの最後の書き手勝利です。モデルはすでにこのフィールドを持っていますが、JSON橋渡しを通じてシリアライズされていません。これを加えれば、片側が真に新しい〜99%の競合を解決できます。残る1%(同じ行の異なるフィールドへの並行編集)は、これまでのアプリにとってフィールドレベルマージやCRDTをスキップできるほど稀なものです。より強い一貫性要件を持つアプリは、上により豊かなマージを重ねます。
iCloud Driveがプロセス間状態の真実の源なら、SwiftDataはどこに収まるのか?
SwiftDataはプロセス内クエリの真実の源です。iOSアプリは、すべてのUIレンダリング、すべての@Query、すべての検索でSwiftDataを読みます。SwiftDataは高速、スキーマ型付け、SwiftUIの観測システムと統合されています。iOSアプリが書き込むとき、変更はまずSwiftDataに行き、その後JSONファイルにエクスポートされます。JSONファイルはプロセス間読み込み(MCPサーバーのビュー)の真実の源です。SwiftDataはプロセス内読み込み(iOS UIのビュー)の真実の源です。両者は調停器を通じて整合を保ちます。
買い物リストそのものにNSUbiquitousKeyValueStoreを使うのは?
NSUbiquitousKeyValueStoreはアプリあたり合計1MB、値あたり1MBに制限され、書き込みもスロットルされ、1024キーの辞書でシリアライズされます。何百もの項目と履歴を持つ買い物リストはバイト数では収まるかもしれませんが、項目ごとの変更をスロットルを通して書き込むのは間違った形です。一括コレクション更新は、アプリが保存する他のすべてのものとレート予算を奪い合います。コレクションの正しい基盤はSwiftData(プロセス内)かiCloud Drive(プロセス間)のいずれかです。NSUbiquitousKeyValueStoreは小さく低頻度のキーバリュー状態のために予約しましょう。設定、最後に選択されたタブ、カウンター、機能フラグの上書きなどです。
アプリの新しいドメインに対してどの基盤を選ぶべきかをどう判断するか?
順番に3つの問いです。第1に:このドメインをiOSアプリプロセスの外で読み書きする必要があるか? もしあれば、iCloud Drive(ファイルベース、通常のファイルI/O)またはCloudKit(Appleフレームワーク経由、または非AppleスタックからのCloudKit Web Services経由)または自分で制御するサーバーが必要です。なければ、SwiftDataがデフォルトです。第2に:これはユーザーのデバイス間で同期する必要があるか? もしあれば、基盤はそれをサポートしなければなりません(iCloud Driveはサポートします。SwiftDataはiCloud同期と組み合わさらなければサポートしません)。第3に:ペイロードはどれくらい大きく、どの頻度で変わるか? 小さい+低頻度ならNSUbiquitousKeyValueStoreに住みます。それ以外はすべて、本物の永続化層が必要です。
参考文献
-
著者の分析、2つのエージェントエコシステム、1つの買い物リスト、2026年4月29日、およびGet Bananasプロジェクトの
Banana List/iCloudBackupManager.swiftにあるiCloud Drive JSON同期層。このアーキテクチャは、SwiftDataと、外部MCPサーバーが読み書きするユーザーのiCloud Driveコンテナ内のJSONファイルを組み合わせます。 ↩↩ -
Apple Developer、「SwiftData」および「Adding and editing persistent data in your app」。
@Modelマクロ、@Attribute制約、Core DataのNSManagedObjectModelとの関係。著者の分析、SwiftDataの本当のコストはスキーマ規律では、安全なスキーマ進化のためのVersionedSchemaとMigrationPlanを扱っています。 ↩ -
Apple Developer、「Synchronizing documents in the iCloud environment」。ファイルベースのデバイス間同期、
NSFileVersionを介した競合解決、共有ファイルへの安全なプロセス内書き込みのためのNSFileCoordinatorAPI。 ↩ -
Apple Developer、「NSUbiquitousKeyValueStore」。デバイス間のキーバリューストレージ。Appleの現在の上限:アプリあたり合計1MB、値あたり1MB、1024キー、キーあたり128 UTF-16文字、書き込みレートはスロットル付き。著者の分析、5つのAppleプラットフォーム、3つの共有ファイルでは、ReturnがこのAPIを使って出荷しているデバイス間タイマーパターンを扱っています。 ↩