ハイライト
iOS 18 と watchOS 11 により、iPhone で作成した Live Activity が Apple Watch の Smart Stack に自動表示されるようになりました。watchOS 版の個別開発も追加 push token の管理も不要で、システムが更新を自動同期します。
主要内容
app はすでに iPhone で Live Activity をサポートしています——Lock Screen、StandBy、Dynamic Island に表示されています。しかしユーザーが手首に着けている Apple Watch はどうでしょうか?それ以前、Live Activity を Watch に表示するには watchOS 版を別途開発し、独立した push token を管理し、2 つの更新ロジックを扱う必要がありました。多くのチームにとって、そのコストは見合いませんでした。
watchOS 11 がこれを変えます。アップグレード後、既存の iOS Live Activity が Apple Watch の Smart Stack に自動表示されます。システムは Dynamic Island の compact leading と compact trailing ビューを使って表示し、上に app 名を表示します。更新も Watch へ自動同期されます——追加 push token も新しいコードも不要です。
ただしこれは出発点に過ぎません。compact ビューは iPhone の Dynamic Island 向けに設計されており、そのまま Watch に持っていくと文字が切れたり情報密度が不足したりします。Apple は supplementalActivityFamilies modifier を提供し、Smart Stack 専用のレイアウトを用意できます。activityFamily 環境値で iPhone Lock Screen(.medium)と Apple Watch Smart Stack(.small)を区別し、それぞれに最適な UI を提供します。
詳細
自動表示の仕組み
watchOS 11 にアップグレードすると、iOS Live Activity の compact leading と compact trailing ビューが Smart Stack に自動表示されます(01:35)。iOS 側で alerting update を受信したとき、ユーザーが Watch フェイスを見ていると、システムは Smart Stack を自動展開して更新を表示します(02:19)。app がフォアグラウンドの場合、画面下部に compact ビューを含む banner が表示されます(02:34)。Live Activity をタップすると全画面表示に入り、デフォルトで「iPhone で開く」オプションが提供されます。
Smart Stack カスタムビューの追加
まず ActivityConfiguration に supplementalActivityFamilies modifier を追加します(04:15):
struct DeliveryLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(
for: DeliveryActivityAttributes.self
) { context in
DeliveryActivityContent(context: context)
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
DeliveryExpandedLeadingView(context: context)
}
DynamicIslandExpandedRegion(.trailing) {
DeliveryExpandedTrailingView(context: context)
}
DynamicIslandExpandedRegion(.bottom) {
DeliveryExpandedBottomView(context: context)
}
} compactLeading: {
DeliveryCompactLeading(context: context)
} compactTrailing: {
DeliveryCompactTrailing(context: context)
} minimal: {
DeliveryMinimal(context: context)
}
}
.supplementalActivityFamilies([.small])
}
}
キーポイント:
.supplementalActivityFamilies([.small])で Smart Stack 用カスタムビューを提供することを宣言します- 追加後、Smart Stack は compact ビューを使わず、
ActivityConfigurationの content closure 内のビューを表示します - この modifier がない場合、Smart Stack はデフォルトで compact leading + compact trailing を表示します
次に、content ビューで activityFamily 環境値を使ってレイアウトを分岐します(04:49):
struct DeliveryActivityContent: View {
@Environment(\.activityFamily) var activityFamily
var context: ActivityViewContext<DeliveryActivityAttributes>
var body: some View {
switch activityFamily {
case .small:
DeliverySmallContent(context: context)
case .medium:
DeliveryMediumContent(context: context)
@unknown default:
DeliveryMediumContent(context: context)
}
}
}
キーポイント:
.smallは Apple Watch Smart Stack に対応します.mediumは iPhone Lock Screen に対応します@unknown defaultは将来追加される可能性のある family タイプを処理します
Smart Stack から Watch App を起動
Watch App がある場合、Live Activity タップ時に iPhone ではなく Watch 側 app を直接開くよう設定できます。Watch app target の Build Settings で Info.plist セクションを見つけ、Supports Launch for Live Activity Attribute Types キーを追加します(05:35)。値が空の場合はすべての Live Activity に適用され、具体的な ActivityAttributes 型名を指定することもできます。
Always On Display への対応
手首を下げると、システムは自動的にダーク配色に切り替え、輝度を下げます。isLuminanceReduced 環境値で明るい要素を調整します(08:37):
struct DeliveryGauge: View {
@Environment(\.isLuminanceReduced) private var isLuminanceReduced
var context: ActivityViewContext<DeliveryActivityAttributes>
var body: some View {
Gauge(value: context.state.progressPercent) {
GaugeLabel(context: context)
}
.tint(isLuminanceReduced ? .gaugeDim : .gauge)
}
}
キーポイント:
isLuminanceReducedがtrueのとき、手首が下がり Always On モードが有効です- このとき明るい要素の輝度を下げるか削除し、可読性を保ちます
- セマンティックカラー(
.primaryなど)は現在の配色に自動適応します
Live Activity にライト外観が必要な場合、.small 分岐で .preferredColorScheme(.light) を設定します(08:57)。Always On モードではシステムが自動的にダークに切り替え、輝度を下げます。
更新頻度とネットワーク
更新同期は自動で、追加 push token は不要です(06:51)。ただし同期頻度には予算制限があり、iOS と同様のしきい値があります。現在の push 更新が iOS 予算内であれば、Apple Watch 側も追加調整は不要です。
ネットワークが制限されている場合、システムは Start、End、alerting update を優先します(08:01)。Smart Stack は「最終接続」時刻を表示し、情報が最新でない可能性を示します。手首を上げると、Live Activity は利用可能な最新データに更新されます。
重要ポイント
-
何を作るか:既存 compact ビューの情報密度を確認します。なぜ価値があるか:compact ビューはゼロコストで Watch に表示されます。静的アイコンや app 名だけだと、Watch 上では無意味な情報になります。どう始めるか:Live Activity を一通り動かし、compact leading/trailing が動的に変化する重要データを表示しているか確認します。
-
何を作るか:
supplementalActivityFamiliesで Smart Stack 用カスタムビューを提供します。なぜ価値があるか:compact ビューは Dynamic Island 向けで、Watch ではスペースと操作パターンが異なります。カスタムビューでより多くの情報とより良い体験を提供できます。どう始めるか:ActivityConfigurationに.supplementalActivityFamilies([.small])を追加し、@Environment(\.activityFamily)でレイアウトを分岐。.small向けの簡略版から始めます。 -
何を作るか:Watch App の直接起動を設定します。なぜ価値があるか:Watch 上の Live Activity タップ時、デフォルトは iPhone app にジャンプし、Watch 側の利用ループが途切れます。どう始めるか:Watch app target の Info.plist に
Supports Launch for Live Activity Attribute Typesを追加。値を空にすれば全タイプに適用されます。 -
何を作るか:Always On Display に対応します。なぜ価値があるか:手首を下げるとダークモードに切り替わり輝度が下がるため、明るい要素は眩しく、焼き付きの原因にもなります。どう始めるか:
@Environment(\.isLuminanceReduced)で状態を検出し、Gauge やプログレスバーなどの輝度を下げます。
関連セッション
- Broadcast updates to your Live Activities — Broadcast Push Notification で大量の Live Activity に更新をプッシュ
- Bring your app’s core features to users with App Intents — App Intents フレームワークの核心概念:Intents、Entities、Queries
- Bring your app to Siri — SiriKit と App Intents で app 機能を Siri に公開
- Build custom swimming workouts with WorkoutKit — WorkoutKit でワークアウトプランを作成・カスタマイズ
コメント
GitHub Issues · utterances