Sandbox はiOSアプリ用の隔離された実行環境であり、ファイルシステム、ネットワーク、ハードウェアリソース、他のアプリのデータへのアクセスを制限します。各アプリはインストール時に独自のSandbox環境を取得し、すべてのファイル操作は自動的にこの隔離領域にリダイレクトされます。Apple App Sandbox Design Guide (2026)によると、サンドボックスアーキテクチャは3つの保護レベルに基づいています。ファイルシステムの隔離、プロセス間通信の制御、entitlementsによる明示的な権限要求を伴うハードウェアリソースの分離です。
要点
Sandbox は、iOSカーネルレベル(XNU — Sandbox.kextカーネル拡張)で実装された強制アクセス制御(Mandatory Access Control)システムです。各アプリは起動時に固有のUUID Sandboxプロファイルを取得し、アクセスを許可されたリソースが決定されます。
Sandboxアーキテクチャには3つの主要コンポーネントがあります。File System Isolation(各アプリは自分のコンテナだけを見る)、Network Access Control(ローカルネットワークへのリクエストが制限される場合がある)、Inter-Process Communication(他のアプリとの直接IPCの禁止)です。AppleはiOS 2.0でSandboxを導入し、それ以降、各メジャーバージョンで制限を大幅に強化しています。
Sandboxはオプションではありません — App Storeのすべてのアプリはサンドボックスで実行されます。開発者はSandboxを無効にしたり、その制限を回避したりすることはできません。禁止されたリソースへのアクセスを試みると、EPERM(Operation not permitted)エラーコードとシステムログへの記録で終了します。
import Foundation
// 別のアプリのファイルへのアクセスを試行 — nilを返す
let otherAppPath = "/var/mobile/Containers/Data/Application/OTHER-UUID/Documents/file.txt"
let data = try? Data(contentsOf: URL(fileURLWithPath: otherAppPath))
// data == nil — Sandboxがアクセスをブロック
// 正しいアクセス — 自分のSandbox内
let fileManager = FileManager.default
guard let documentsURL = fileManager.urls(
for: .documentDirectory,
in: .userDomainMask
).first else { return }
let myFileURL = documentsURL.appendingPathComponent("notes.txt")
try "Hello, Sandbox!".write(to: myFileURL, atomically: true, encoding: .utf8)
iOSの各アプリのSandboxには、Foundation API経由でアクセスできるいくつかの定義済みディレクトリが含まれています。物理メディア上の場所は /var/mobile/Containers/Data/Application/{UUID}/ ですが、開発者はこのパスを直接使用すべきではありません。異なるiOSバージョンではデバイスの再起動のたびに変化します。
Sandboxの主なディレクトリ:Bundle(.app — 読み取り専用、実行可能コードとリソースを含む)、Documents(ユーザーデータ、iCloudにバックアップ)、Library(Caches、Preferences、Application Support — バックアップルールが異なる)、tmp(一時ファイル、容量不足時にシステムが削除)。各ディレクトリには独自のライフサイクルと保存ポリシーがあります。
Sandboxの物理パスは、NSHomeDirectory()またはFileManager.url(for: .documentDirectory)で取得できます。AppleはURLベースのAPIの使用を推奨しています。ファイルシステムの内部構造を抽象化し、デスクトップ上のmacOS Sandboxが変更されても安定するためです。
| Sandboxディレクトリ | FileManagerでの取得 | 権限 |
|---|---|---|
| Documents | .documentDirectory | 読み書き |
| Bundle | Bundle.main.bundlePath | 読み取り専用 |
| Library | .libraryDirectory | 読み書き |
| tmp | NSTemporaryDirectory() | 読み書き |
| App Group | .containerURL(forSecurityApplicationGroupIdentifier:) | 読み書き |
iOSでは、他のアプリのファイルシステムへの直接アクセスは完全にブロックされています。開発者が他のアプリのコンテナUUIDを知っていても、カーネルレベルのSandboxは読み取りまたは書き込みの試行時にエラーを返します。これは、Sandboxがより柔軟なmacOSとの根本的な違いです。
Appleはアプリ間データ交換のための3つの正当なメカニズムを提供しています。UIDocumentPickerViewController(ユーザーがシステムインターフェイスでファイルを選択し、アプリがSecurity-Scoped URLを取得)、Share Extension(他のアプリへデータを渡す拡張)、App Groups(同じ開発者のアプリ用の共有ディレクトリ)です。
UIDocumentPickerは、事前設定なしに他のアプリのファイルにアクセスする唯一の方法です。ユーザーは標準のシステムピッカーで明示的にファイルを選択し、iOSはアプリに一時的なSecurity-Scoped URLを提供します。アクセスはピッカーが閉じられるまで、またはstopAccessingSecurityScopedResourceが呼び出されるまで有効です。
Security-Scoped Bookmarkは、アプリの起動間でSandbox外のファイルへのアクセスを維持できるiOSのメカニズムです。ユーザーがUIDocumentPickerでファイルを選択すると、アプリはSecurity-Scoped URLからブックマークを作成し、UserDefaultsや他のストレージに保存できます。
次の起動時に、アプリはURLByResolvingBookmarkDataを介してアクセスを復元し、Security-Scoped URLが返されます。次に、ファイルの読み取り前にstartAccessingSecurityScopedResourceを呼び出し、終了後にstopAccessingSecurityScopedResourceを呼び出す必要があります。呼び出しのバランスが必須です — 各startには対応するstopが必要であり、そうしないとシステムがSecurity-Scopedリソースの上限を使い果たします。
// Security-Scoped Bookmarkを作成
func createBookmark(for url: URL) -> Data? {
return try? url.bookmarkData(
options: .minimalBookmark,
includingResourceValuesForKeys: nil,
relativeTo: nil
)
}
// ブックマークデータをURLに解決
func resolveBookmark(data: Data) -> URL? {
var isStale = false
let url = try? URL.byResolvingBookmarkData(
data,
options: .withoutUI,
relativeTo: nil,
bookmarkDataIsStale: &isStale
)
if isStale {
// ブックマークが古いため、新規作成が必要
}
return url
}
重要な制限:Security-Scoped Bookmarksは、自分のSandbox内のファイルには機能しません — UIDocumentPickerまたはiCloud Driveで取得したファイルにのみ有効です。ブックマークには、どのアプリがどのファイルへのアクセスを要求しているかをシステムが識別できるSecurity-Scopedデータが含まれています。アプリの証明書が失効または変更されると、ブックマークは無効になります。
App Groupsは、同じ開発者の複数のアプリ(およびその拡張)が共通のSandboxディレクトリを共有できるiOSのメカニズムです。有効にするには、XcodeでApp Groups Capabilityを追加し、すべての対象アプリに同じグループ識別子を指定する必要があります。
共有App Groupsディレクトリは各アプリのSandboxの外にありますが、グループのすべてのアプリは読み書きへの完全なアクセスを持っています。これにより、メインアプリ、Today Widget、Watch Extension、Share Extensionの間で、ファイル、データベース(App Group内のStore URLを持つCore Data)、UserDefaults(initWithSuiteName経由)を交換できます。
Appleは、アプリとその拡張間の状態同期にApp Groupsを使用することを推奨しています。たとえば、Today Widgetは、メインアプリが最新データを書き込む共有App Groupsディレクトリからデータを読み取ることができます。同時に、各アプリは他のApp Groupsからは隔離されたままです — 同じグループ識別子を持つアプリだけがアクセスできます。
iOSのSandboxは、開発時に考慮しなければならない多くの厳格な制限を課します。主なもの:動的コードの禁止(Sandbox外でのコードの読み込みと実行)、ユーザーの許可なしでのアドレス帳、カレンダー、写真への直接アクセスの禁止(Privacy framework)、子プロセス作成の制限(forkとexecは禁止)。
ネットワーク:アプリはTCP/UDP経由で任意のリモートサーバーに接続できますが、localhostへのアクセスは制限されています — 他のアプリはあなたのアプリ内のサーバーに接続できません(デバッグビルドを除く)。App Storeアプリでは、マルチキャストとブロードキャストUDPもブロックされます。
ハードウェアリソース:カメラ、マイク、位置情報、Bluetooth、HealthKitへのアクセスには、システムダイアログによるユーザーの明示的な許可が必要です。各リソースタイプについて、iOSは個別のentitlementと、理由の説明を持つInfo.plistキー(NSPhotoLibraryUsageDescription、NSCameraUsageDescription)を使用します。Info.plistに理由の説明なしで許可を要求すると、アプリが終了します。
よくある質問
Sandbox は、ファイルシステム、ネットワーク、他のアプリのデータへのアクセスを制限するiOSアプリ用の隔離された実行環境です。各アプリは固有のSandboxコンテナを持ち、そのアクセスはSandbox.kextを介してiOSカーネルレベルで制御されます。
アプリで利用可能:Documents(ユーザーデータ)、Library(Caches、Preferences、Application Support)、tmp(一時ファイル)、Bundle(読み取り専用)。App Groupディレクトリは、同じ開発者グループのアプリで利用できます。
UIDocumentPickerViewController経由 — ユーザーがシステムインターフェイスでファイルを選択します。iOSはSecurity-Scoped URLを提供し、stopAccessingSecurityScopedResourceが呼び出されるまで有効です。代替手段は、アプリ間でデータを転送するShare Extensionです。
Security-Scoped Bookmark は、アプリの起動間でSandbox外のファイルへのアクセスを維持するDataです。bookmarkDataを介してSecurity-Scoped URL(UIDocumentPickerから取得)から作成されます。次の起動時に、ブックマークはURLByResolvingBookmarkDataで復元されます。
いいえ、App StoreアプリではSandboxを無効にできません。ジェイルブレイク済みデバイスでは無効化可能ですが、App Storeへの公開とは互換性がありません。開発者はシミュレータでSandboxなしでテストできますが、実際のデバイスでは常にSandboxが適用されます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。