-
Bring Live Activities to Mac
Discover how to drive Live Activities from your Mac app. Explore how Live Activities appear in the menu bar and Dynamic Island. Learn how to define your data model, create compact and expanded views with SwiftUI, and drive interactive updates using App Intents.
Chapters
- 0:00 - Introduction
- 0:54 - Live Activities on Mac
- 1:43 - Define the data model
- 2:51 - Build the views
- 4:40 - Start and update an activity
- 5:38 - Add actions
- 6:25 - End an activity
- 6:44 - Next steps
Resources
- Starting and updating Live Activities with ActivityKit push notifications
- Displaying live data with Live Activities
Related Videos
WWDC23
-
Search this video…
-
-
2:36 - Define the Live Activity data model
import ActivityKit struct CurtainActivityAttributes: ActivityAttributes { let scenesPerAct: [Int] let showTitle: String struct ContentState: Codable, Hashable { var isPlaying: Bool var curtainOpen: Bool var actIndex: Int var sceneIndexInAct: Int } } -
3:20 - Configure compact, minimal, and expanded views
import SwiftUI import WidgetKit struct CurtainActivityWidget: Widget { var body: some WidgetConfiguration { ActivityConfiguration( for: CurtainActivityAttributes.self ) { context in CurtainActivityMenuBarExpandedContent( state: context.state, showTitle: context.attributes.showTitle) } dynamicIsland: { context in DynamicIsland { DynamicIslandExpandedRegion(.leading) { CurtainLabel(state: context.state) } DynamicIslandExpandedRegion(.trailing) { ActLabel(state: context.state) } DynamicIslandExpandedRegion(.center) { SceneLabel(state: context.state) } DynamicIslandExpandedRegion(.bottom) { ExpandedBottom(state: context.state) } } compactLeading: { StatusGlyph(state: context.state) } compactTrailing: { CompactTrailing(state: context.state) } minimal: { StatusGlyph(state: context.state) } } } } -
5:23 - Update a running Live Activity
contentState.curtainOpen = false let content = ActivityContent( state: self.currentContentState, staleDate: nil ) await activity.update( content, alertConfiguration: alertConfiguration ) -
6:02 - Define an App Intent action
struct SetPlacesReadyIntent: AppIntent { // ... func perform() async throws -> some IntentResult { // ... var state = activity.content.state state.placesReady = self.ready let content = ActivityContent(state: state, staleDate: nil) await activity.update( content, alertConfiguration: .announcement(self.ready ? "Ready" : "Not Ready") ) return .result() } } -
6:16 - Trigger the intent from buttons
private struct PlacesReadyButtons: View { var body: some View { HStack { Button(intent: SetPlacesReadyIntent(ready: false)) { Text("Not Ready") } .tint(.red) Button(intent: SetPlacesReadyIntent(ready: true)) { Text("Ready") } .tint(.green) } } } -
6:32 - End a Live Activity
// End a Live Activity await activity.end(nil, dismissalPolicy: .immediate)
-