ハイライト
サードパーティ撮影 App がロック画面から直接起動可能に。ユーザーはコントロールセンター、Action Button、ロック画面コントロールからビューファインダーに入り、デバイスをアンロックせずに撮影できます。
主要内容
ユーザーが写真を撮るためにスマートフォンを取り出すとき、期待するのは「押したら撮れる」こと。「アンロック → App を探す → ビューファインダーの読み込み待ち」ではありません。システムカメラ App は常にロック画面から直接使用できましたが、サードパーティ撮影 App にはこの能力がありませんでした——iOS 18 まで。
iOS 18 の LockedCameraCapture フレームワークがこのギャップを埋めます。新しい App Extension タイプ——Locked Camera Capture Extension——を提供し、撮影 UI をコントロールセンター、Action Button、ロック画面コントロールからアンロック不要で起動できます。操作パスは「アンロック → App を探す → 撮影」から「コントロールを押す → 直接撮影」に短縮。
ライフサイクル全体が「ロック画面セキュリティ」を中心に設計:拡張起動後は直ちにビューファインダーを表示しなければならず、さもなければシステムがプロセスを終了。撮影完了後、コンテンツは sessionContentURL ディレクトリまたは PhotoKit 経由で保存。ユーザーが深い操作(SNS への共有など)を必要とする場合、拡張は openApplication を呼びアンロックを要求し、メイン App へシームレスに遷移。拡張が dismissed されると session コンテンツはメイン App のコンテナへ自動移行し、拡張コンテナは消去。各レイヤーがロック画面状態でのデータ分離を保証。
詳細
Locked Camera Capture Extension のエントリ
拡張のエントリは LockedCameraCaptureExtension プロトコルに準拠する SwiftUI 構造体。body は LockedCameraCaptureUIScene を返す(11:21):
@main
struct ClownTownCaptureExtension: LockedCameraCaptureExtension {
var body: some LockedCameraCaptureUIScene {
LockedCameraCaptureUIScene { session in
CaptureView(session: session)
}
}
}
キーポイント:
@mainは拡張のエントリポイントLockedCameraCaptureExtensionは iOS 18 の新プロトコル。Xcode はビューファインダーとシャッターボタンを含むテンプレートを提供LockedCameraCaptureUISceneの初期化クロージャはLockedCameraCaptureSessionオブジェクトを受け取る。拡張とシステムの相互作用の核心
LockedCameraCaptureSession が提供する能力
Session オブジェクトは拡張実行中の中心ハブ。3 つの重要な能力を提供(12:41):
// 1. 永続化ディレクトリ:撮影データを保存する唯一の推奨場所
let contentURL = session.sessionContentURL
// 2. コンテンツ処理完了をマーク。システムがディレクトリを削除可能に
session.invalidateSessionContent()
// 3. メイン App の起動を要求(デバイスアンロックをトリガー)
session.openApplication(
NSUserActivity(activityType: NSUserActivityTypeLockedCameraCapture)
)
キーポイント:
sessionContentURLは拡張コンテナ内のディレクトリを指す。拡張 dismissed 後に唯一メイン App コンテナへ移行されるコンテンツ- 拡張コンテナ内の他のデータはすべて消去——永続化が必要なデータを別の場所に保存しない(08:46)
invalidateSessionContent()呼び出し後、以前書き込んだコンテンツは削除されるが、ディレクトリ自体は引き続き書き込み可能(13:38)openApplicationはユーザー能動的操作(ボタンタップなど)時のみ呼び出し。自動トリガー不可(13:51)
CameraCaptureIntent と Control の連携
ユーザーが拡張を起動するコントロールが必要。WidgetKit の Control と新しい CameraCaptureIntent で実装(14:54):
struct ClownTownCaptureIntent: CameraCaptureIntent {
static var title: LocalizedStringResource = "ClownTown Capture"
// appContext は App と拡張間で設定を共有
var clownTownContext: ClownTownContext?
func perform() async throws -> some IntentResult {
// context を読み取り、拡張の初期状態を設定
return .result()
}
}
キーポイント:
CameraCaptureIntentは iOS 18 の新 Intent タイプ。撮影拡張起動専用- Intent は 3 つの target に同時含める必要がある:Widget Extension、Capture Extension、メイン App(15:17)
appContextは App と拡張間の状態共有チャネルだがサイズ制限あり。大きすぎると永続化不可(16:08)updateAppContext()で共有状態を更新。両側が最新値を読める(16:56)
メイン App 側での撮影コンテンツ受信
メイン App は LockedCameraCaptureManager で拡張の撮影コンテンツを取得(20:24):
let manager = LockedCameraCaptureManager.shared
// 保留中の全 session ディレクトリを取得
let urls = manager.sessionContentURLs
// 新しい session コンテンツを非同期監視
for await update in manager.sessionContentUpdates {
switch update {
case .added(let url):
// 新着撮影コンテンツを処理
processContent(at: url)
manager.invalidateContent(at: url)
case .removed(let url):
break
}
}
キーポイント:
sessionContentUpdatesは AsyncSequence。初期値に既存の全 session URL を含み、その後追加・削除を継続監視(20:53)- 拡張から App への遷移時、最新 session ディレクトリは App 起動後に準備完了する場合がある。一度きりの読み取りより非同期シーケンスを推奨(21:19)
invalidateContent(at:)呼び出し後、ディレクトリコンテンツが削除され.removed更新イベントがトリガー(21:27)
ロック画面状態でのセキュリティ制限
拡張はロック画面状態で厳格に制限(05:34):
- 直ちにカメラビューファインダーを表示しなければならず、さもなければシステムが拡張を終了
- ハードウェアボタンイベント(音量キーでの撮影/録画)には
AVCaptureEventInteractionを使用必須 - ネットワークアクセス不可
- App の共有 Group Container への読み書き不可
- App の SharedPreferences へのアクセス不可
- ロック画面下の PhotoKit は現在 session に書き込んだ写真と動画の読み取りのみ許可
重要ポイント
-
何をするか:既存撮影 App にロック画面ショートカットを追加。なぜ価値があるか:ユーザーは撮影時に速度を求める。ロック画面直アクセスは操作摩擦を大幅に下げ、サードパーティ App にシステムカメラと同等の起動優先度を与える。始め方:Xcode で Locked Camera Capture Extension target を新規作成。既存 SwiftUI ビューファインダービューを再利用。Control と Intent を追加。
-
何をするか:sessionContentURL で撮影データのオフライン安全保存を実現。なぜ価値があるか:拡張のネットワークとコンテナアクセスは禁止されるが、session ディレクトリは拡張 dismissed 後にメイン App へ自動移行。「先に撮影、後で同期」アーキテクチャが自然に形成——撮影時は完全オフライン、App 実行時にアップロード。始め方:撮影データを
session.sessionContentURLに書き込み。メイン App のLockedCameraCaptureManager.sessionContentUpdatesで非同期取得・処理。 -
何をするか:appContext で拡張と App 間でユーザー設定を同期。なぜ価値があるか:拡張は共有コンテナと設定にアクセス不可だが、App で選択したフィルターや撮影モードはロック画面撮影シーンでも継続すべき。始め方:
CameraCaptureIntentのappContextに重要設定を保存。拡張起動時に context から読み取り。拡張内で設定変更時はupdateAppContext()で書き戻し。 -
何をするか:「拡張撮影 → アンロック遷移 → 深度編集」の一貫ワークフローを設計。なぜ価値があるか:多くの撮影シーンは後続操作(フィルター、共有、編集)が必要。拡張はネットワークと完全リソースにアクセス不可。openApplication がシームレス遷移を提供。始め方:深度操作が必要なボタンで
session.openApplication()を呼び出し。NSUserActivityの userInfo でコンテキストを渡し。メイン App のhandleActivityで対応 UI 状態に復帰。
関連セッション
- Extend your app’s controls across the system — コントロールセンター、ロック画面、Action Button のカスタムコントロール作成方法
- Design App Intents for system experiences — コントロール、Spotlight、Siri などシステム級体験を駆動する App Intents の設計方法
- Keep colors consistent across captures — 撮影シーンでの色彩一貫性維持
- Use HDR for dynamic image experiences in your app — App への HDR 画像・動画統合
- Build compelling spatial photo and video experiences — 没入型空間写真・動画体験の作成
コメント
GitHub Issues · utterances