briefly. • Always on Lock Screen, separated from other push notifications. • Can be created, updated without app alive. • No permission needed in advance.
struct ExampleLiveActivityAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { // Dynamic stateful properties go here var progress: Double } // Fixed non-changing properties go here let taskName: String }
16.1+) and iPad (iOS 17+) • Lock Screen • Notification Center • Banner • For device does not have Dynamic Island • Alert is set in config • StandBy (iOS 17+) • macOS (iOS 26+) Lock Screen macOS StandBy
provided, system will use default UI for Apple Watch and CarPlay. • Automatically supported by iOS. • Default UI uses Compact Leading and Compact Trailing from Dynamic Island. Leading Trailing App Name Default Style
as creating, updating and ending a Live Activity • From • Print and copy token from console • Generate the authentication token manually • Manually modify payload • CLI command to send push notification • To • Build a mini CMS to • Collect token • Generate authentication token and call APNs API • Provide web UI to modify payload and manage tokens
AI era, this should be easier than before ╭───────────────────────────────────────────────────╮ │ * Welcome! │ │ │ │ /help for help, /status for your current setup │ ╰───────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │ > You’re a experienced backend developer who works with iOS developer a lots, │ │ now you need to help the iOS developer to build a CMS to manage Live Activities │ │ tokens and provide UI to modify payload data and send push notification │ │ (sample prompt) │ ╰─────────────────────────────────────────────────────────────────────────────────╯
Activities remotely • Token-based connection to APNs • Need to collect push-to-start & update token • Live Activities push is not supported by push platforms at very beginning
Create, update and end all on local side • No server needed • Simple, clear state transition • Easy to manage state • Less edge cases • No major business impact would be preferred • Easy to convince stakeholders
friendly • Especially for those huge, complicated projects • Complicated dependencies • Separate Logic and UI • Build independent target for preview purpose only • Static Framework for speed up build but less flexible than Dynamic Framework • Mergeable Libraries could be a solution
we still need to support old versions. struct ExampleLiveActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: ExampleLiveActivityAttributes.self) { … } dynamicIsland: { … } .supplementalActivityFamilies([.medium, .small]) } } Activity Families
OS version to decide whether to add modifier or not. struct ExampleLiveActivity: Widget { var activityConfiguration: ActivityConfiguration<ExampleLiveActivityAttributes> { ActivityConfiguration(for: ExampleLiveActivityAttributes.self) { context in … } dynamicIsland: { context in … } } var body: some WidgetConfiguration { if #available(iOS 18, *) { // for iOS 18.0+, customized for Apple Watch return activityConfiguration .supplementalActivityFamilies([.medium, .small]) } else { // for old versions return activityConfiguration } } }
ExampleContentView: View { @Environment(\.activityFamily) var activityFamily let title: String let progress: Double var body: some View { if activityFamily == .small { … } else { … } } }
var body: some View { if activityFamily == .small { SmallView() } else { MediumView() } } } Activity Families 1. Extract View first, prepare Views for .medium and .small 2. Prepare a container view which can use activityFamily Medium View Small View activityFamily == .small Activity Families View
and .small 2. Prepare a container view which can use activityFamily 3. Prepare another container view which can check OS version Medium View Small View Activity Families View Example Content View iOS 18+ struct ExampleContentView: View { let title: String let progress: Double var body: some View { if #available(iOS 18, *) { ActivityFamiliesView() } else { MediumView() } } }
only from server updates, but also local transition from host app to widget extension. • In the case of media upload, I need to send the thumbnails to Live Activity. • Directly using Data?
(iOS 17.2+) • Only available for users who have seen Live Activity before • Update token (iOS 16.1+) • Similar to collect push notification token, but for every Live Activitiy instance • Consider error cases and retry mechanism