Live Activityは、iPhoneのロック画面やDynamic Islandに表示される動的ウィジェットで、配達状況、スポーツのスコア、タイマー、音楽再生などのリアルタイム情報を表示します。ActivityKit(Swift、iOS 16.1+)とWidgetKitを組み合わせて実装されます。Live Activityはローカルまたはプッシュ通知により更新され、複数の状態をサポートし、イベント終了後にシステムによって終了されます。詳細はActivityKit Documentationをご覧ください。
重要なポイント
Live ActivityはWidgetKitの拡張機能で、iPhoneのロック画面とDynamic Islandに動的コンテンツを表示します。システムタイマーで更新される静的ウィジェットとは異なり、Live Activityはアプリによって起動され、限られた時間だけ存続します — アクティブなActivityは最大8時間、完了後は最大4時間です。ユーザーはデバイスをロック解除せずに最新データを確認できます:配送注文の状況、タクシーの目的地までの距離、試合結果、ワークアウトの進捗など。
ActivityKitはLive Activitiesを扱うためのフレームワークで、iOS 16.1で導入されました。Activityのリクエスト、更新、終了のためのAPIを提供します。Activityはコンテンツと状態を持つオブジェクトです。コンテンツ(ActivityContent)は静的データを定義し、状態(ActivityState)は時間とともに変化する動的データを定義します。システム自体が新しい状態をレンダリングするタイミングを決定します — これによりバッテリーを節約し、スムーズなアニメーションを保証します。
各Live ActivityはActivityIDによって一意に識別され、1つのプロセス(作成したアプリ)に結び付けられます。システムはメモリ不足やバッテリー残量が少ない場合にActivityを終了することがあります。開発者はActivityKitデリゲートを介して強制終了の通知を受け取り、復元用に最後の状態を保存できます。
Live Activityのアーキテクチャは2つのフレームワークに基づいています:WidgetKitはSwiftUIビューのレンダリングを担当し、ActivityKitはActivityのライフサイクルを担当します。開発者はLiveActivityConfigurationをサポートするWidgetBundleを作成します。各設定はデータ型(AttributesとState)と、システムがロック画面とDynamic IslandでレンダリングするSwiftUIビューを定義します。データはActivityAttributesを介して渡されます — コンテンツ用のletフィールドと状態用のvarフィールドを持つ構造体です。
| コンポーネント | 目的 | API |
|---|---|---|
| Attributes | Activity全体の静的データ | let name: String, let icon: String |
| ContentState | 更新時に変更される動的状態 | var progress: Double, var status: Status |
| Activity | Activityのリクエストおよび管理オブジェクト | Activity.request(attributes:content:) |
| PushToken | サーバープッシュ更新用のトークン | activity.pushToken publisher |
| ActivityUI | ロック画面とDynamic Island用のSwiftUIビュー | LockScreenView, ExpandedView, CompactView |
Activityのライフサイクルには3つのフェーズがあります:アクティブ(システムが表示・更新)、最終(Activityは終了したがUIは4時間表示される)、削除(システムがUIを削除する)。アプリはいつでもActivityを終了できます。システムもActivityを強制終了します — 例えば、デバイスの再起動時や8時間の制限が切れた時などです。
import ActivityKit
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable & Hashable {
var status: DeliveryStatus
var estimatedMinutes: Int
}
var orderNumber: String
var restaurantName: String
}
WidgetBundleは@mainマクロを介してLive Activityを登録します:ウィジェットはLiveActivityConfigurationを含む設定のリストを返します。この設定に基づいて、システムは期待するデータ型と、さまざまな状態(Dynamic Island用のコンパクト、最小、拡張)でUIをどのようにレンダリングするかを認識します。
Activityの作成はActivityKitへのリクエストから始まります。アプリは初期データとともにActivity.request(attributes:content:pushType:)を呼び出します。システムはデバイスでDynamic Islandが利用可能かどうかを確認し、Activityオブジェクトを返します。アクティブなActivityの制限を超えた場合、リクエストは失敗する可能性があります — 通常、同時に5つまでです。リクエストが成功すると、システムはロック画面にウィジェットを表示し、可能であればDynamic Islandにも表示します。
let attributes = DeliveryAttributes(
orderNumber: "A-1234",
restaurantName: "Pizza House"
)
let initialState = DeliveryAttributes.ContentState(
status: DeliveryStatus.preparing,
estimatedMinutes: 30
)
do {
let activity = try await Activity<DeliveryAttributes>.request(
attributes: attributes,
content: ActivityContent(state: initialState, staleDate: nil),
pushType: .token
)
print("Activity started: \(activity.id)")
} catch {
print("Failed: \(error)")
}
Live Activity用のSwiftUIビューはWidgetKitのLockScreenView、ExpandedView、CompactView構造体を使用します。ビューは現在の属性と状態を含むコンテキスト(ActivityViewContext)を受け取ります。システムから新しい状態が届くと、ビューは自動的に更新されます。Live Activityは限られたSwiftUIコンポーネントのみをサポートします — Text、Image、HStack、VStackといくつかのモディファイアです。
各Live Activityビューは軽量で高速でなければなりません — システムは重いビューのレンダリングを拒否します。レンダリング時間の制限は1フレームあたり30ミリ秒です。アニメーションは状態間のシステムトランジションに制限されています — Live Activityではカスタムアニメーションは利用できません。レンダリングはロック画面の応答性を優先するWidgetKitのバックグラウンドプロセスで実行されます。
ローカル更新 — アプリはactivity.update(using:)を呼び出してActivityの状態を更新します。このメソッドは新しいContentStateと、更新時に通知を表示するためのオプションのAlertConfigurationを受け入れます。ローカル更新は高速です — システムは次のレンダリングサイクルでビューを再描画し、通常1〜2秒以内です。頻繁な更新(タイマー、ストップウォッチ)にはローカルモードを使用してください — プッシュよりも信頼性が高く高速です。
let updatedState = DeliveryAttributes.ContentState(
status: DeliveryStatus.outForDelivery,
estimatedMinutes: 10
)
await activity.update(
ActivityContent<DeliveryAttributes.ContentState>(
state: updatedState,
staleDate: Date().addingTimeInterval(60)
),
alertConfiguration: AlertConfiguration(
title: "Order out for delivery",
body: "Arriving in 10 min"
)
)
プッシュ更新 — サーバーがJSON形式で新しい状態を含むActivityKitプッシュ通知を送信します。このために、アプリはactivity.pushTokenパブリッシャーからpushTokenを取得し、サーバーに渡します。サーバーは新しいContentStateを含むペイロードでAPNsにPOSTリクエストを送信します。システムはプッシュを受信し、状態をデコードし、アプリの関与なしにLive Activityを更新します — これによりアプリが閉じられていてもActivityを更新できます。
プッシュ更新は、頻度の低い更新(5〜10分ごとの配達状況)にはより効率的です — アプリはネットワーク接続を維持する必要がありません。1〜2秒ごとの頻繁な更新にはローカルメソッドを使用してください。サーバーペイロードにはContentStateの変更可能なフィールドのみが含まれます — 静的なAttributesデータはActivity作成時にのみ送信されます。
Dynamic IslandはiPhone 14 Pro、15 Pro以降のハードウェア・ソフトウェア領域で、Live Activityのコンテンツに適応します。システムは自動的にActivityを3つのモードで表示します:コンパクト(カットアウトの左側にアイコン+短いテキスト)、最小(アイコンのみ)、拡張(情報付きの300ptの長方形)。開発者はこれらのモードを直接制御しません — システムが優先度と利用可能なスペースに基づいてモードを選択します。
struct DeliveryLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: DeliveryAttributes.self) { context in
LockScreenView(context: context)
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedContent {
ExpandedView(context: context)
}
} compactLeading: {
CompactLeadingView(context: context)
} compactTrailing: {
CompactTrailingView(context: context)
} minimal: {
MinimalView(context: context)
}
}
}
}
Dynamic Islandはインタラクティブ性をサポートしています — ユーザーが領域をタップするとアプリに入るか拡張ビューが開きます。コンパクトモードをタップすると拡張モードに切り替わり、左にスワイプするとActivityが最小モードになります。拡張モードのボタン(一時停止/キャンセル)はSwiftUIのLinkを介して処理されます — システムがディープリンクURLでアプリを起動し、処理はUIApplicationDelegateで行われます。
Dynamic Islandの制限:拡張モードの幅は最大300pt、コンパクトテキストは最大30文字です。色とフォントはシステムテーマに一致します — カスタマイズは制限されています。モード間のトランジションアニメーションはシステム定義でカスタマイズできません。複数のアプリがアクティブなActivityを持っている場合、Dynamic Islandは起動時間とコンテンツタイプに基づいて優先順位をつけて表示します。
よくある質問
通常のWidgetKitウィジェットは静的情報を表示し、最小15〜30分間隔でシステムタイマーで更新されます。Live Activityはロック画面とDynamic Islandでリアルタイムに動的データを表示します。Live Activityはアプリによって起動され、最大8時間存続し、イベント終了後にシステムによって終了されます。常に存在するウィジェットとは異なります。
Live Activityは2つの更新モードをサポートしています:ローカル — アプリがActivityKit APIを介していつでも状態を更新、プッシュ更新 — サーバーがActivityKitプッシュ通知を送信し、システムがそれをウィジェットの新しい状態に変換します。バッテリー残量が少ない場合、システムは充電が接続されるまでLive Activityを停止することがあります。
Live ActivitiesはiOS 16.1以降のiPhoneで利用可能です。iPhone 14 Pro以降では、Live ActivityはDynamic Islandにも表示されます。iPadでは、Live Activityはロック画面でのみサポートされています — iPadではDynamic Islandは利用できません。Apple Watchは直接Live Activitiesをサポートしていませんが、完了通知を表示できます。
システムはアクティブなLive Activitiesの数を制限します — 通常、すべてのアプリで同時に5つまでです。制限を超えて開始しようとすると、ActivityKitがエラーを返します。各Live Activityは複数の状態を持つことができます — 例えば、保留中、輸送中、フードオーダーの配達済みなど。完了後、ActivityはUIにさらに4時間残ります。
はい、アプリは通知送信の許可をリクエストする必要があります — Live Activityはシステム通知チャネルを使用します。ユーザーは設定で特定のアプリのLive Activityを無効にできます。初回起動時に、ActivityKitは許可を求めるダイアログを表示します。許可がない場合、Activityリクエストは失敗します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。