分享

Displaying live data with Live Activities | Apple Developer Documentation

 wintelsui 2023-02-15 发布于北京

Overview

Live Activities display your app’s most current data on the iPhone Lock Screen and in the Dynamic Island. This allows people to see live information at a glance.

To offer Live Activities, add code to your existing widget extension or create a new widget extension if your app doesn’t already include one. Live Activities use WidgetKit functionality and SwiftUI for their user interface. ActivityKit’s role is to handle the life cycle of each Live Activity: You use its API to request, update, and end a Live Activity and to receive ActivityKit push notifications.

For design guidance, see Human Interface Guidelines > Live Activities.

Review Live Activity presentations

Live Activities come in different presentations for the Lock Screen and the Dynamic Island. The Lock Screen presentation appears on all devices. On an unlocked device that doesn’t support the Dynamic Island, the Lock Screen presentation also appears as a banner for Live Activity updates that include an alert configuration. For example, if a person uses Mail on a device that doesn’t support the Dynamic Island while the Live Activity receives an update with an alert configuration, the system displays the Lock Screen presentation as a banner at the top of the screen to let them know about the updated Live Activity. Two screenshots of iPhone that doesn’t support the Dynamic Island and shows a Live Activity for a delivery app. They show the Live Activity on the Lock Screen and the same presentation on the Home Screen as a banner.

Devices that support the Dynamic Island display Live Activities in the Dynamic Island using several presentations. When there’s only one ongoing Live Activity, the system uses the compact presentation. It’s composed of two separate presentations: one that displays on the leading side of the TrueDepth camera, and one that displays on the trailing side. Although the leading and trailing presentations are separate views, they form a cohesive view in the Dynamic Island, representing a single piece of information from your app. People can tap a compact Live Activity to open the app and get more details about the event or task. An illustration of the Dynamic Island with a Live Activity that appears in the compact leading and trailing presentations.

When multiple Live Activities from several apps are active, the system uses the circular minimal presentation to display two of them in the Dynamic Island. The system chooses a Live Activity from one app to appear attached to the Dynamic Island while it presents a Live Activity from another app detached from the Dynamic Island. As with a compact Live Activity, people can tap a minimal Live Activity to open the app and get more details about the event or task. An illustration of the Dynamic Island with a Live Activity that appears in the minimal presentation.

When people touch and hold a Live Activity in a compact or minimal presentation, the system displays the content in an expanded presentation. An illustration of the Dynamic Island with a Live Activity that appears in the expanded presentations.

To add support for Live Activities in your app, you must support all presentations.

Understand constraints

A Live Activity can be active for up to eight hours unless your app or a person ends it. After this 8-hour limit, the system automatically ends it. When a Live Activity ends, the system immediately removes it from the Dynamic Island. However, the Live Activity remains on the Lock Screen until a person removes it or for up to four additional hours before the system removes it — whichever comes first. As a result, a Live Activity remains on the Lock Screen for a maximum of twelve hours.

For more information about ending a Live Activity, see “End the Live Activity” below.

The system requires image assets for a Live Activity to use a resolution that’s smaller or equal to the size of the presentation for a device. If you use an image asset that’s larger than the size of the Live Activity presentation, the system might fail to start the Live Activity. For information about the sizes of Live Activity presentations, see Human Interface Guidelines > Live Activities.

Each Live Activity runs in its own sandbox, and — unlike a widget — it can’t access the network or receive location updates. To update the dynamic data of an active Live Activity, use the ActivityKit framework in your app or allow your Live Activities to receive ActivityKit push notifications as described in Updating and ending your Live Activity with ActivityKit push notifications.

Add support for Live Activities to your app

The code that describes the user interface of your Live Activity is part of your app’s widget extension. If you already offer widgets in your app, add code for the Live Activity to your existing widget extension and reuse code between your widgets and Live Activities. However, although Live Activities leverage WidgetKit’s functionality, they aren’t widgets. In contrast to the timeline mechanism you use to update your widgets’ user interface, you update a Live Activity from your app with ActivityKit or with ActivityKit push notifications.

To add support for Live Activities to your app:

  1. Create a widget extension if you haven’t added one to your app and make sure “Include Live Activity” is selected when you add a widget extension target to your Xcode project. For more information on creating a widget extension, see WidgetKit and Creating a Widget Extension.

  2. If your project includes an Info.plist file, add the Supports Live Activities entry to it, and set its Boolean value to YES. Alternatively, open the Info.plist file as source code, add the NSSupportsLiveActivities key, then set the type to Boolean and its value to YES. If your project doesn’t have an Info.plist file, add the Supports Live Activities entry to the list of custom iOS target properties for your iOS app target and set its value to YES.

  3. Add code that defines an ActivityAttributes structure to describe the static and dynamic data of your Live Activity.

  4. Use the ActivityAttributes you defined to create the ActivityConfiguration.

  5. Add code to configure, start, update, and end your Live Activities.

Define a set of static and dynamic data

After you add a widget extension target to your Xcode project that includes Live Activities, describe the data that your Live Activity displays by implementing ActivityAttributes. The ActivityAttributes inform the system about static data that appears in the Live Activity. You also use ActivityAttributes to declare the required custom Activity.ContentState type that describes the dynamic data of your Live Activity. In the example below, PizzaDeliveryAttributes describes the following static data: the number of pizzas ordered, the amount the customer needs to pay, and the order number. Note how the code defines the Activity.ContentState to encapsulate dynamic data: the name of the driver who delivers the pizza and the estimated delivery time. Additionally, the example defines the type alias PizzaDeliveryStatus to make the code more descriptive and easy to read.


import Foundation
import ActivityKit


struct PizzaDeliveryAttributes: ActivityAttributes {
    public typealias PizzaDeliveryStatus = ContentState


    public struct ContentState: Codable, Hashable {
        var driverName: String
        var deliveryTimer: ClosedRange<Date>
    }


    var numberOfPizzas: Int
    var totalAmount: String
    var orderNumber: String
}

Add Live Activities to the widget extension

Live Activities leverage WidgetKit. After you add code to describe the data that appears in the Live Activity with the ActivityAttributes structure, add code to return an ActivityConfiguration in your widget implementation.

The following example uses the PizzaDeliveryAttributes structure from the previous example:


import SwiftUI
import WidgetKit


@main
struct PizzaDeliveryActivityWidget: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
            // Create the presentation that appears on the Lock Screen and as a
            // banner on the Home Screen of devices that don't support the
            // Dynamic Island.
            // ...
        } dynamicIsland: { context in
            // Create the presentations that appear in the Dynamic Island.
            // ...
        }
    }
}

If your app already offers widgets, add the Live Activity to your WidgetBundle. If you don’t have a WidgetBundle — for example, if you only offer one widget — create a widget bundle as described in Creating a Widget Extension and then add the Live Activity to it. The following example shows how you can use an if statement with an availability clause to only add a Live Activity to your widget bundle if the device supports Live Activities:


@main
struct PizzaDeliveryWidgets: WidgetBundle {
    var body: some Widget {
        FavoritePizzaWidget()


        if #available(iOS 16.1, *) {
            PizzaDeliveryLiveActivity()
        }
    }
}

Create the Lock Screen presentation

To create the user interface of the Live Activity, you use SwiftUI in the widget extension you created earlier. Similar to widgets, you don’t provide the size of the user interface for your Live Activity but let the system determine the appropriate dimensions.

Start with the presentation that appears on the Lock Screen. The following code displays the information that the PizzaDeliveryAttributes struct describes with standard SwiftUI views:


@main
struct PizzaDeliveryWidget: Widget {    
    var body: some WidgetConfiguration { 
        ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
            // Create the presentation that appears on the Lock Screen and as a
            // banner on the Home Screen of devices that don't support the
            // Dynamic Island.
            LockScreenLiveActivityView(context: context)
        } dynamicIsland: { context in
            // Create the presentations that appear in the Dynamic Island.
            // ...
        }
    }
}


struct LockScreenLiveActivityView: View {
    let context: ActivityViewContext<PizzaDeliveryAttributes>
    
    var body: some View {
        VStack {
            Spacer()
            Text("\(context.state.driverName) is on their way with your pizza!")
            Spacer()
            HStack {
                Spacer()
                Label {
                    Text("\(context.attributes.numberOfPizzas) Pizzas")
                } icon: {
                    Image(systemName: "bag")
                        .foregroundColor(.indigo)
                }
                .font(.title2)
                Spacer()
                Label {
                    Text(timerInterval: context.state.deliveryTimer, countsDown: true)
                        .multilineTextAlignment(.center)
                        .frame(width: 50)
                        .monospacedDigit()
                } icon: {
                    Image(systemName: "timer")
                        .foregroundColor(.indigo)
                }
                .font(.title2)
                Spacer()
            }
            Spacer()
        }
        .activitySystemActionForegroundColor(.indigo)
        .activityBackgroundTint(.cyan)
    }
}

On a device that doesn’t support the Dynamic Island, the system displays the Lock Screen presentation as a banner if the device is unlocked and you update your Live Activity using the update(_:alertConfiguration:) function and include an AlertConfiguration.

Create the compact and minimal presentations

Live Activities appear in the Dynamic Island of devices that support it. When you start one or more Live Activities and no other app starts a Live Activity, the compact leading and trailing presentations appear together to form a cohesive presentation in the Dynamic Island for one Live Activity.

An illustration that shows compact leading and trailing presentations for a Live Activity of a food delivery app.

When more than one app starts a Live Activity, the system chooses which Live Activities are visible and displays two Live Activities using the minimal presentation for each: One minimal presentation appears attached to the Dynamic Island while the other appears detached.

An illustration of the Dynamic Island with a Live Activity that appears in the minimal presentation.

The following example shows how the pizza delivery app provides the required compact and minimal presentations using standard SwiftUI views:


import SwiftUI
import WidgetKit


@main
struct PizzaDeliveryWidget: Widget {    
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
            // Create the presentation that appears on the Lock Screen and as a
            // banner on the Home Screen of devices that don't support the
            // Dynamic Island.
            // ...
        } dynamicIsland: { context in
            // Create the presentations that appear in the Dynamic Island.
            DynamicIsland {
                // Create the expanded presentation.
                // ...
            } compactLeading: {
                Label {
                    Text("\(context.attributes.numberOfPizzas) Pizzas")
                } icon: {
                    Image(systemName: "bag")
                        .foregroundColor(.indigo)
                }
                .font(.caption2)
            } compactTrailing: {
                Text(timerInterval: context.state.deliveryTimer, countsDown: true)
                    .multilineTextAlignment(.center)
                    .frame(width: 40)
                    .font(.caption2)
            } minimal: {
                VStack(alignment: .center) {
                    Image(systemName: "timer")
                    Text(timerInterval: context.state.deliveryTimer, countsDown: true)
                        .multilineTextAlignment(.center)
                        .monospacedDigit()
                        .font(.caption2)
                }
            }
            .keylineTint(.cyan)
        }
    }
}

Create the expanded presentation

In addition to the compact and minimal presentations, you must support the expanded presentation. It appears when a person touches and holds a compact or minimal presentation, and it also appears briefly for Live Activity updates.

An illustration of the Dynamic Island with a Live Activity that appears in the expanded presentation.

Use the DynamicIslandExpandedRegionPosition to specify detailed instructions where you want SwiftUI to position your content. The following example shows how the pizza delivery app creates its expanded presentation:


@main
struct PizzaDeliveryWidget: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
            // Create the presentation that appears on the Lock Screen and as a
            // banner on the Home Screen of devices that don't support the
            // Dynamic Island.
            LockScreenLiveActivityView(context: context)
        } dynamicIsland: { context in
            // Create the presentations that appear in the Dynamic Island.
            DynamicIsland {
                // Create the expanded presentation.
                DynamicIslandExpandedRegion(.leading) {
                    Label("\(context.attributes.numberOfPizzas) Pizzas", systemImage: "bag")
                        .foregroundColor(.indigo)
                        .font(.title2)
                }
                
                DynamicIslandExpandedRegion(.trailing) {
                    Label {
                        Text(timerInterval: context.state.deliveryTimer, countsDown: true)
                            .multilineTextAlignment(.trailing)
                            .frame(width: 50)
                            .monospacedDigit()
                    } icon: {
                        Image(systemName: "timer")
                            .foregroundColor(.indigo)
                    }
                    .font(.title2)
                }
                
                DynamicIslandExpandedRegion(.center) {
                    Text("\(context.state.driverName) is on their way!")
                        .lineLimit(1)
                        .font(.caption)
                }
                
                DynamicIslandExpandedRegion(.bottom) {
                    Button {
                        // Deep link into your app.
                    } label: {
                        Label("Call driver", systemImage: "phone")
                    }
                    .foregroundColor(.indigo)
                }
            } compactLeading: {
                // Create the compact leading presentation.
                // ...
            } compactTrailing: {
                // Create the compact trailing presentation.
                // ...
            } minimal: {
                // Create the minimal presentation.
                // ...
            }
            .keylineTint(.yellow)
        }
    }
}

To render views that appear in the expanded Live Activity, the system divides the expanded presentation into different areas. Note how the example returns a DynamicIsland that specifies several DynamicIslandExpandedRegion objects. Pass the following DynamicIslandExpandedRegionPosition values to lay out your content at a specified position in the expanded presentation:

  • center places content below the TrueDepth camera.

  • leading places content along the leading edge of the expanded Live Activity next to the TrueDepth camera and wraps additional content below it.

  • trailing places content along the trailing edge of the expanded Live Activity next to the TrueDepth camera and wraps additional content below it.

  • bottom places content below the leading, trailing, and center content.

An illustration that shows the center, leading, trailing, and bottom positions for content for the expanded presentation in the Dynamic Island.

To render content that appears in the expanded Live Activity, the system first determines the width of the center content while taking into account the minimal width of the leading and trailing content. The system then places and sizes the leading and trailing content based on its vertical position. By default, leading and trailing positions receive an equal amount of horizontal space.

You can tell the system to prioritize one of the DynamicIslandExpandedRegion views by passing a priority to the init(_:priority:content:) initializer. The system renders the view with the highest priority with the full width of the Dynamic Island. The following illustration shows leading and trailing positions in an expanded presentation with higher priority to render them below the TrueDepth camera.

An illustration that shows the leading and trailing positions in an expanded presentation with higher priority to render them below the TrueDepth camera.

Set custom content margins

Limiting the content you display is key to offering glanceable, easy-to-read Live Activities. Aim to use the system’s default content margins for your Live Activities and only show content that’s relevant to a person. However, you may want to change the system’s default content margin to display more content or provide a custom user interface that matches your app. To set custom content margins, use contentMargins(_:_:for:). The following example results in a margin of 8 points for the trailing edge of an expanded Live Activity.


@main
struct PizzaDeliveryWidget: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
            // Create the presentation that appears on the Lock Screen and as a
            // banner on the Home Screen of devices that don't support the
            // Dynamic Island.
            // ...
        } dynamicIsland: { context in
            // Create the presentations that appear in the Dynamic Island.
            } compactLeading: {
                // Create the compact leading presentation.
                // ...
            } compactTrailing: {
                // Create the compact trailing presentation.
                // ...
            } minimal: {
                // Create the minimal presentation.
                // ...
            }
            .contentMargins(.trailing, 8, for: .expanded)
        }
    }
}

If you repeatedly use the contentMargins(_:_:for:) modifier, the system uses the innermost specified values for a mode.

Use custom colors

By default, the system uses the default primary color for text and a background color for your Live Activity that best fits a person’s Lock Screen. To set a custom tint color, use the activityBackgroundTint(_:) view modifier. Additionally, use the activitySystemActionForegroundColor(_:) view modifier to customize the text color of the auxiliary button that allows people to end the Live Activity on the Lock Screen.

To set the translucency of the custom background tint color, use the opacity(_:) view modifier or specify an opaque background color.

Create a deep link into your app

People tap a Live Activity to launch your app. To improve the user experience, you can use widgetURL(_:) to create a deep link into your app from the Lock Screen, compact leading, compact trailing, and minimal presentations. When the compact leading and trailing presentations are visible, make sure both link to the same screen in your app.

The expanded presentation offers additional options to create deep links into your app for more utility using SwiftUI’s Link. For example, the pizza delivery app could include two SwiftUI views. One view could open a map in the app for the current delivery, and the second view could open a screen that allows people to call the person who delivers the pizza.

If you don’t explicitly provide a deep link into your app with widgetURL(_:) or Link, the system launches your app and passes a NSUserActivity object to the scene(_:willContinueUserActivityWithType:) and scene(_:continue:) callbacks. Implement both callbacks and check whether the NSUserActivity object’s activityType is NSUserActivityTypeLiveActivity, and add code to open a screen in your app that fits the context of the active Live Activity.

Provide accessibility labels

Designing with accessibility in mind is a foundational principle when creating an app. It also applies to Live Activities. To allow people to customize how they interact with your Live Activity and to make sure VoiceOver for your Live Activity works correctly, add accessibility labels for the SwiftUI view you create for each presentation. The example below shows how the pizza delivery app uses the accessibilityLabel(_:) modifier to add an accessibility label to the MinimalPizzaDeliveryView. Accessibility labels for the expanded, minimal, compact leading, and compact trailing presentations each need accessibility labels that fit the view’s content.


import SwiftUI
import WidgetKit


@main
struct PizzaDeliveryWidget: Widget {    
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
            // Create the presentation that appears on the Lock Screen and as a
            // banner on the Home Screen of devices that don't support the
            // Dynamic Island.
            // ...
        } dynamicIsland: { context in
            // Create the presentations that appear in the Dynamic Island.
            DynamicIsland {
                DynamicIslandPizzaDeliveryView(context: context)
                    .accessibilityLabel("Add an accessibility label here.")  
            } compactLeading: {
                CompactLeadingPizzaDeliveryView(context: context)
                    .accessibilityLabel("Add an accessibility label here.")
            } compactTrailing: {
                CompactTrailingPizzaDeliveryView(context: context)
                    .accessibilityLabel("Add an accessibility label here.")
            } minimal: {
                MinimalPizzaDeliveryView(context: context)
                    .accessibilityLabel("Add an accessibility label here.")
            }
            .keylineTint(.cyan)
        }
    }
}

Add accessibility labels for each SwiftUI view you use as needed and make sure your accessibility labels fit the Live Activity content. To review API that allows you to add accessible descriptions to SwiftUI views, see Accessible descriptions.

For guidance on providing content descriptions, see Human Interface Guidelines > Accessibility > VoiceOver > Content descriptions.

Make sure Live Activities are available

Live Activities are only available on iPhone. If your app is available on multiple platforms and offers a widget extension, make sure Live Activities are available at runtime. Additionally, people can choose to deactivate Live Activities for an app in the Settings app.

To see if Live Activities are available and if a person allowed your app to use Live Activities:

  • Use areActivitiesEnabled to synchronously determine whether to show a user interface in your app for starting a Live Activity.

  • Receive asynchronous user authorization updates by observing any user authorization changes with the activityEnablementUpdates stream and respond to them accordingly.

Configure the Live Activity

Before you can start a Live Activity in your app, you need to configure it with an ActivityContent object. It encapsulates the ActivityAttributes structure and additional configuration information:

  • The staleDate tells the system when the Live Activity content becomes outdated.

  • The relevanceScore determines which of your Live Activities appears in the Dynamic Island and the order of your Live Activities on the Lock Screen.

While setting the staleDate is optional, it’s helpful when you want to make sure your Live Activity doesn’t display outdated content. At the specified date, the Live Activity’s activityState changes to ActivityState.stale. By using the activityStateUpdates stream, your app can monitor the activity state and respond to outdated Live Activities that haven’t received updates. For example, an app that allows people to track a sports game sets a stale date to mark the Live Activity as outdated a few minutes in the future. While a person has network connectivity, the app updates the Live Activity with the latest game information and advances the stale date. If a person enters an area without network connectivity, the app can’t update the Live Activity with new information. When the Live Activity becomes stale, the app responds to the outdated Live Activity and updates it with text to indicate that the displayed information is outdated.

If your app starts more than one Live Activity, provide a relevance score to determine the order of your Live Activities on the Lock Screen and which of your Live Activities appears in the Dynamic Island:

  • If you don’t provide a relevance score or if Live Activities have the same relevance score, the system shows the first Live Activity you started in the Dynamic Island.

  • If you use different relevance scores, the system shows the Live Activity with the highest relevance score in the Dynamic Island.

The system expects relative values for the relevance score. Assign a higher value for an important Live Activity content update — for example, a score of 100 — and use lower values for less important Live Activity content updates — for example, 50.

The following example creates the initial content state for the pizza delivery app’s Live Activity and the activity content object that encapsulates the content and configuration for a Live Activity that allows people to track their pizza order. Note how it sets a stale date that’s 30 minutes after the Live Activity started and doesn’t specify a relevance score because it’s unlikely that a person places multiple orders at the same time.


if ActivityAuthorizationInfo().areActivitiesEnabled {
    var future = Calendar.current.date(byAdding: .minute, value: (Int(minutes) ?? 0), to: Date())!
    future = Calendar.current.date(byAdding: .second, value: (Int(seconds) ?? 0), to: future)!
    let date = Date.now...future
    let initialContentState = PizzaDeliveryAttributes.ContentState(driverName: "Bill James", deliveryTimer:date)
    let activityAttributes = PizzaDeliveryAttributes(numberOfPizzas: 3, totalAmount: "$42.00", orderNumber: "12345")
    
    let activityContent = ActivityContent(state: initialContentState, staleDate: Calendar.current.date(byAdding: .minute, value: 30, to: Date())!)
    
    // Add code to start the Live Activity here.
    // ...
}

Start the Live Activity

You start a Live Activity in your app’s code while the app is in the foreground with the request(attributes:content:pushType:) function. Pass the ActivityAttributes and ActivityContent objects you created to it and, if you implement ActivityKit push notifications, the pushType parameter.


if ActivityAuthorizationInfo().areActivitiesEnabled {
    // Create the activity attributes and activity content objects.
    // ...


    // Start the Live Activity.            
    do {
        deliveryActivity = try Activity.request(attributes: activityAttributes, content: activityContent)
        print("Requested a pizza delivery Live Activity \(String(describing: deliveryActivity?.id)).")
    } catch (let error) {
        print("Error requesting pizza delivery Live Activity \(error.localizedDescription).")
    }
}

For more information on using ActivityKit push notifications to update your Live Activity, see Updating and ending your Live Activity with ActivityKit push notifications.

Update the Live Activity

When you start a Live Activity from your app, update the data that appears in the Live Activity using the update(_:) function of the Activity object you received when you started the Live Activity. To retrieve your app’s active Live Activities, use activities.

For example, the pizza delivery app could update the Live Activity that shows the delivery status with a new delivery time and a new driver. It could also use the update(_:alertConfiguration:) function to display an alert on iPhone and Apple Watch that tells a person about new Live Activity content as shown in the following example:


var future = Calendar.current.date(byAdding: .minute, value: (Int(minutes) ?? 0), to: Date())!
future = Calendar.current.date(byAdding: .second, value: (Int(seconds) ?? 0), to: future)!
let date = Date.now...future
let updatedDeliveryStatus = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Anne Johnson", deliveryTimer: date)
let alertConfiguration = AlertConfiguration(title: "Delivery update", body: "Your pizza order will arrive in 25 minutes.", sound: .default)
let updatedContent = ActivityContent(state: updatedDeliveryStatus, staleDate: nil)


await deliveryActivity?.update(updatedContent, alertConfiguration: alertConfiguration)

On Apple Watch, the system uses the title and body attributes for the alert. On iPhone, the system doesn’t show a regular alert but instead shows the expanded Live Activity in the Dynamic Island or the Lock Screen presentation as a banner on devices without the Dynamic Island.

Animate content updates

When you define the user interface of your Live Activity, the system ignores any animation modifiers — for example, withAnimation(_:_:) and animation(_:value:) — and uses the system’s animation timing instead. However, the system performs some animation when the dynamic content of the Live Activity changes. Text views animate content changes with blurred content transitions, and the system animates content transitions for images and SF Symbols. If you add or remove views from the user interface based on content or state changes, views fade in and out. Use the following view transitions to configure these built-in transitions: opacity, move(edge:), slide, push(from:), or combinations of them. Additionally, request animations for timer text with numericText(countsDown:).

End the Live Activity

Always end a Live Activity after the associated task or live event ends. A Live Activity that ended remains on the Lock Screen until the person removes it or the system removes it automatically. The automatic removal depends on the dismissal policy you provide to the end(_:dismissalPolicy:) function. Always include an updated Activity.ContentState to ensure the Live Activity shows the latest and final content update after it ends. This is important because the Live Activity can remain visible on the Lock Screen for some time after it ends.

The following example shows how the pizza delivery app ends a Live Activity that shows the delivery status for an order when the pizza was delivered:


let finalDeliveryStatus = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Anne Johnson", deliveryTimer: Date.now...Date())
let finalContent = ActivityContent(state: finalDeliveryStatus, staleDate: nil)


Task {
    for activity in Activity<PizzaDeliveryAttributes>.activities {
        await activity.end(finalContent, dismissalPolicy: .default)
        print("Ending the Live Activity: \(activity.id)")
    }
}

The example above uses the default dismissal policy. As a result, the Live Activity appears on the Lock Screen for some time after it ends to allow a person to glance at their phone to see the latest information. A person can choose to remove the Live Activity at any time, or the system removes it automatically four hours after it ended.

To immediately remove the Live Activity that ended from the Lock Screen, use immediate. Alternatively, use after(_:) to specify a date within a four-hour window. While you can provide any date, the system removes the ended Live Activity after the given date or after four hours from the moment the Live Activity ended — whichever comes first.

A person can remove your Live Activity from their Lock Screen at any time. This ends your Live Activity, but it doesn’t end or cancel the person’s action that started the Live Activity. For example, a person may remove the Live Activity for their pizza delivery from the Lock Screen, but this doesn’t cancel the pizza order. When the person or the system removes the Live Activity, the ActivityState changes to ActivityState.dismissed.

Update or end your Live Activity with a push notification

In addition to updating and ending a Live Activity from your app with ActivityKit, update or end a Live Activity with an ActivityKit push notification that you send from your server to the Apple Push Notification service (APNs). To learn more about using push notifications to update your Live Activities, see Updating and ending your Live Activity with ActivityKit push notifications.

Keep track of updates

When you start a Live Activity, ActivityKit returns an Activity object. In addition to the id that uniquely identifies each activity, the Activity offers sequences to observe content, activity state, and push token updates. Use the corresponding sequence to receive updates in your app, keep your app and Live Activities in sync, and respond to changed data:

  • To observe changes to ongoing Live Activities, use activityUpdates.

  • To observe the state of an ongoing Live Activity — for example, to determine whether it’s active or has ended — use activityStateUpdates.

  • To observe changes to the dynamic content of a Live Activity, use contentUpdates.

  • To observe changes to the push token of a Live Activity, use pushTokenUpdates.

The following example shows how the pizza delivery app tracks updates for ongoing Live Activities:


// Observe updates for ongoing pizza delivery Live Activities.
for await activity in Activity<PizzaDeliveryAttributes>.activityUpdates {
    print("Pizza delivery details: \(activity.attributes)")
}

Observe active Live Activities

Your app can start more than one Live Activity. For example, a sports app may allow a person to start a Live Activity for each live sports game they’re interested in. If your app starts multiple Live Activities, keep track of ongoing Live Activities for your app using the activities property to make sure your app is aware of all ongoing Live Activities that ActivityKit tracks. Another use case for fetching all activities is to maintain Live Activities that are in progress and make sure you don’t keep any activities running for longer than needed. For example, the system may stop your app, or your app may crash while a Live Activity is active. When the app launches the next time, check if any activities are still active, update your app’s stored Live Activity data, and end any Live Activity that’s no longer relevant.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多