App Groupは、アプリとその拡張機能間でデータを共有するためのコンテナを作成するiOSのメカニズムです。これがないと、各プロセス(メインアプリ、ウィジェット、共有拡張機能)は独立したサンドボックス内で動作し、隣接するコンポーネントのデータにアクセスできません。Apple Developer Documentation(2026年)によると、App Groupはエンタイトルメントで指定された単一のグループ識別子を通じてこの問題を解決します。これはiOSエコシステムで一貫したユーザーエクスペリエンスを構築するための基本的なツールです。
重要ポイント
App Groupは、同じ開発者の複数プロセスに共有ストレージ領域を提供するiOSオペレーティングシステムのメカニズムです。これがないと、各拡張機能は独自のサンドボックスで動作し、他のコンポーネントが書き込んだデータを読み取ることができません。App Groupは、正しいエンタイトルメントを持つすべてのプロセスがアクセスできるディレクトリをファイルシステム上に作成することで、この分離問題を解決します。
グループ識別子はプレフィックスgroup.で始まり、プロジェクトのエンタイトルメントファイルで指定されます。Xcodeでは、この識別子はCapabilitiesを通じて追加され、システムは自動的にそれをアプリの署名に含めます。設定後、すべてのグループメンバーはコンテナ内のLibrary/Application Support/にある共有ディレクトリにアクセスできます。
Apple WWDC 2020 Session 10026によると、App Groupは3つの主要なシナリオをカバーしています:NSUserDefaultsによる設定の同期、FileManagerによるファイル共有、単一ストアでのCore Data共有。各シナリオでは、対応するAPIでグループ識別子を指定するだけで済みます。
iOSは、com.apple.security.application-groupsエンタイトルメントを持つ任意のプロセスが初めて実行されるときに共有コンテナを作成します。物理的には、コンテナはシステムディレクトリに配置され、そのパスはメインアプリや拡張機能のサンドボックスとは異なりますが、すべての認可されたプロセスには読み取りおよび書き込み権限があります。
Appleは、team IDとコード署名の組み合わせによりApp Groupのセキュリティを保証します。同じ開発者証明書で署名されていないプロセスは、グループコンテナにアクセスできません。これにより、異なる開発者間でのデータ漏洩を防ぎます。
識別子の形式は:group.<team-id>.<name>です。例:group.ABC123DEFG.widget-data。1つのデバイスに複数のグループを作成でき、それぞれに独自のメンバーセットがあります。1つのアプリが複数のApp Groupに同時に属することができ、これは異なる拡張機能のデータを分離するのに便利です。
// Get the App Group container URL
guard let containerURL = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.widget")
else { return }
// Create a file in the shared container
let fileURL = containerURL.appendingPathComponent("shared.data")
try "Hello from main app".write(to: fileURL, atomically: true, encoding: .utf8)
FileManagerは、containerURL(forSecurityApplicationGroupIdentifier:)メソッドを提供し、共有ディレクトリのURLを返します。各プロセスでこのメソッドを個別に呼び出すことが重要です。パスは物理的に同じですが、各プロセスは独自のセキュリティ視点からそれを見ます。
XcodeでApp Groupを有効にするには、Capabilitiesから始めます。App Groupsトグルがプロジェクトにエンタイトルメントを追加します。Apple Developer Portalでも、アプリ識別子にこの機能を含める必要があります。これがないと、実機でのコード署名が機能しません。
Xcodeでプロジェクトを開き、アプリターゲットを選択してSigning & Capabilitiesタブに移動します。+をクリックしてApp Groupsを選択します。新しいグループを作成するか、既存のグループを選択します。共有コンテナへのアクセスが必要な各拡張機能について、同じ手順を繰り返します。すべての参加者が同じグループ識別子を使用する必要があります。
Capabilitiesを有効にすると、Xcodeは自動的にcom.apple.security.application-groupsキーと識別子の配列を含む.entitlementsファイルを作成します。すべての必要な拡張機能が、グループ識別子に正しいteam IDを持つこのファイルを持っていることを確認してください。
<!-- Example entitlements file -->
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.example.shared</string>
</array>
プロジェクトに複数の拡張機能(Today Widget、Share Extension、Notification Service)がある場合、それぞれが同じグループで独自のエンタイトルメントファイルを持つ必要があります。いずれかのターゲットでエンタイトルメントが欠如していると、拡張機能が共有データを認識できない一般的な原因になります。
アプリとその拡張機能間でデータを同期する最も簡単な方法は、suite nameを指定したUserDefaultsです。標準のUserDefaults.standardの代わりに、App Group識別子でインスタンスを作成すると、すべてのプロセスが同じ設定を読み取ります。
Apple Human Interface Guidelinesによると、このメカニズムは状態の同期に適しています:選択したテーマ、お気に入り、オンボーディングフラグなど。ただし、大量のデータや同時書き込み操作には適していません。その場合はファイルまたはCore Dataを使用してください。
// Write to UserDefaults App Group (main app)
let defaults = UserDefaults(suiteName: "group.com.example.shared")
defaults?.set(true, forKey: "isDarkMode")
defaults?.synchronize()
// Read from UserDefaults App Group (widget extension)
let sharedDefaults = UserDefaults(suiteName: "group.com.example.shared")
let isDark = sharedDefaults?.bool(forKey: "isDarkMode") ?? false
注意:suiteNameを使用したUserDefaultsインスタンスは各プロセスで個別に作成されますが、共有コンテナ内の同じplistファイルから読み取ります。synchronize()メソッドは即時のディスク書き込みを保証します。iOS 13+では、システムが定期的にデータを同期するため省略可能です。
より複雑なシナリオでは、App Groupは共有ファイルシステムへのアクセスを提供します。コンテナディレクトリに作成されたファイルは、グループのすべてのプロセスからアクセス可能です。これにより、共有のCore Dataデータベース、画像キャッシュ、一時ファイルが可能になります。
共有Core Dataストアを使用するには、App Groupディレクトリ内にある.sqliteファイルのURLを指定してNSPersistentContainerを作成します。一度に1つのプロセスのみがデータベースに書き込むようにしてください。同時書き込みはデータを破損する可能性があります。典型的なアーキテクチャは、メインアプリが書き込み、拡張機能が読み取りを行います。
// Setup Core Data with App Group container
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "SharedModel")
guard let appGroupURL = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.shared")
else { return container }
let storeURL = appGroupURL.appendingPathComponent("SharedModel.sqlite")
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
container.loadPersistentStores { _, error in
if let error = error { fatalError(error.localizedDescription) }
}
return container
}()
代替アプローチとして、ファイルベースの画像キャッシュがあります。NSCacheはメモリ内にのみ存在しますが、App Groupを介してキャッシュされた画像を共有ディレクトリのディスクに保存できます。ウィジェット拡張機能は同じファイルにアクセスし、追加のネットワークダウンロードなしで最新のデータを表示できます。
| シナリオ | 推奨API | データサイズ |
|---|---|---|
| 設定とフラグ | UserDefaults suiteName | 最大1 KB |
| 画像キャッシュ | FileManager + NSCache | 最大100 MB |
| 構造化データ | Core Dataストア | 最大500 MB |
| 一時ファイル | FileManager一時 | 最大50 MB |
共有ファイルを扱う際は、システムがいつでも拡張機能を終了する可能性があることに注意してください。複数のプロセスが同時に書き込む際のデータ破損を防ぐために、アクセス調整にはNSFileCoordinatorを使用してください。
よくある質問
App Groupは、アプリとその拡張機能間でデータを保存するための共有コンテナを作成するiOSのメカニズムです。同じグループ識別子を持つプロセスが、ファイルシステム上の単一のディレクトリを通じてファイル、UserDefaults設定、Core Dataデータを交換できるようにします。
XcodeでターゲットのCapabilitiesを開き、App Groupsを有効にしてgroup.*形式の識別子を追加します。次に、共有コンテナにアクセスする必要がある各拡張機能について同じ手順を繰り返します。すべての参加者が同じグループ識別子を使用していることを確認してください。
すべてのタイプのiOS拡張機能がApp Groupをサポートしています:Today Widget(ウィジェット拡張機能)、Share Extension、Notification Service Extension、Custom Keyboardなど。各拡張機能は、メインアプリと同じグループ識別子を持つ別個のエンタイトルメントファイルが必要です。
はい、ただしアプリが同じ開発者証明書で署名され、同じteam IDを持っている場合に限ります。Appleはコード署名によるセキュリティを保証しています。異なる開発者の2つのアプリは、同じグループ識別子でも同じコンテナにアクセスできません。
小さな設定にはsuite name付きのUserDefaults、ファイルにはFileManager、構造化データにはCore Dataを使用します。これらのAPIはすべてApp Groupディレクトリで動作します。初期化時にグループ識別子を指定するだけです。Core Dataの場合は、ストアURLが共有ディレクトリを指していることを確認してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。