使用實(shí)時(shí)活動(dòng)顯示實(shí)時(shí)數(shù)據(jù)
提供實(shí)時(shí)活動(dòng),在靈動(dòng)島和鎖定屏幕上顯示您的應(yīng)用程序的最新數(shù)據(jù)。
概述
實(shí)時(shí)活動(dòng)在 iPhone 鎖定屏幕和靈動(dòng)島中顯示您的應(yīng)用程序的最新數(shù)據(jù)。這使人們可以一目了然地看到實(shí)時(shí)信息。
要提供實(shí)時(shí)活動(dòng),請(qǐng)將代碼添加到您現(xiàn)有的小部件擴(kuò)展或創(chuàng)建一個(gè)新的小部件擴(kuò)展(如果您的應(yīng)用尚未包含)。Live Activity 使用WidgetKit功能和SwiftUI繪制用戶界面。ActivityKit 的作用是處理每個(gè) Live Activity 的生命周期:您使用它的 API 來請(qǐng)求、更新和結(jié)束 Live Activity。
筆記
現(xiàn)場(chǎng)活動(dòng)僅在 iPhone 上可用。
要提供實(shí)時(shí)活動(dòng)( Live Activity)代碼需要添加到小組件中(iOS14 以后的widget)使用WidgetKit功能,使用SwiftUI繪制界面。iOS16新增了ActivityKit,其作用是處理每個(gè) Live Activity 的生命周期:您使用它的 API 來請(qǐng)求、更新和結(jié)束 Live Activity。
查看實(shí)時(shí)活動(dòng)要求和限制
除非您的應(yīng)用程序或用戶結(jié)束它,否則 Live Activity 最多可以處于活動(dòng)狀態(tài)八小時(shí)。超過此限制,系統(tǒng)自動(dòng)結(jié)束。當(dāng) Live Activity 結(jié)束時(shí),系統(tǒng)會(huì)立即將其從 Dynamic Island 中移除。但是,實(shí)時(shí)活動(dòng)會(huì)一直保留在鎖定屏幕上,直到用戶將其刪除或系統(tǒng)將其刪除前最多四個(gè)小時(shí)(以先到者為準(zhǔn))。因此,實(shí)時(shí)活動(dòng)會(huì)在鎖定屏幕上最多保留十二小時(shí)。
有關(guān)結(jié)束 Live Activity 的更多信息,請(qǐng)參閱下面的“在您的應(yīng)用內(nèi)結(jié)束 Live Activity”。
每個(gè) Live Activity 在自己的沙箱中運(yùn)行,并且 - 與小部件不同 - 它無法訪問網(wǎng)絡(luò)或接收位置更新。要更新活動(dòng) Live Activity 的動(dòng)態(tài)數(shù)據(jù),請(qǐng)?jiān)谀膽?yīng)用程序中使用 ActivityKit 框架或允許您的 Live Activity 接收遠(yuǎn)程推送通知,如使用遠(yuǎn)程推送通知更新和結(jié)束您的 Live Activity 中所述。
筆記
ActivityKit 更新和遠(yuǎn)程推送通知更新的更新動(dòng)態(tài)數(shù)據(jù)大小不能超過 4KB。
實(shí)時(shí)活動(dòng)針對(duì)鎖定屏幕和靈動(dòng)島提供不同的視圖。鎖定屏幕視圖出現(xiàn)在所有設(shè)備上。支持靈動(dòng)島的設(shè)備使用以下視圖顯示實(shí)時(shí)活動(dòng):靈動(dòng)島的緊湊前視圖、緊湊尾視圖、最小視圖和擴(kuò)展視圖。
當(dāng)人在靈動(dòng)島中觸摸并持有緊湊或最小視圖以及實(shí)時(shí)活動(dòng)更新時(shí),會(huì)出現(xiàn)擴(kuò)展視圖。在不支持靈動(dòng)島的解鎖設(shè)備上,展開的視圖顯示為實(shí)時(shí)活動(dòng)更新的橫幅。
為確保系統(tǒng)可以在每個(gè)位置顯示您的 Live Activity,您必須支持所有視圖。
為您的應(yīng)用添加對(duì)實(shí)時(shí)活動(dòng)的支持
描述 Live Activity 用戶界面的代碼是應(yīng)用的小部件擴(kuò)展的一部分。如果您已經(jīng)在應(yīng)用程序中提供小部件,則可以將 Live Activity 的用戶界面代碼添加到現(xiàn)有的小部件擴(kuò)展中,并且可以在小部件和 Live Activity 之間重用代碼。然而,盡管 Live Activity 利用了 WidgetKit 的功能,但它們并不是小部件。與您用于更新小部件用戶界面的時(shí)間線機(jī)制相比,您可以使用 ActivityKit 或遠(yuǎn)程推送通知從您的應(yīng)用程序更新實(shí)時(shí)活動(dòng)。
筆記
您可以創(chuàng)建一個(gè)小部件擴(kuò)展來采用實(shí)時(shí)活動(dòng),而無需提供小部件。但是,請(qǐng)考慮同時(shí)提供小部件和實(shí)時(shí)活動(dòng),以允許人們?cè)谥髌聊缓玩i定屏幕上添加可瀏覽的信息和個(gè)人風(fēng)格。
為您的應(yīng)用添加對(duì)實(shí)時(shí)活動(dòng)的支持:
如果您還沒有向您的應(yīng)用程序添加一個(gè)小部件擴(kuò)展,請(qǐng)創(chuàng)建一個(gè)小部件擴(kuò)展。有關(guān)創(chuàng)建小部件擴(kuò)展的更多信息,請(qǐng)參閱WidgetKit和創(chuàng)建小部件擴(kuò)展。
打開應(yīng)用程序的
Info.plist
文件,添加Supports Live Activities
條目,并將其布爾值設(shè)置為 YES。或者,將 Info.plist 文件作為源代碼打開,添加鍵NSSupportsLiveActivities
,然后將類型設(shè)置為布爾值并將其值設(shè)置為 YES。如果您的項(xiàng)目沒有Info.plist
文件,請(qǐng)將條目添加到您的 iOS 應(yīng)用程序目標(biāo)的自定義 iOS 目標(biāo)屬性列表中。添加定義ActivityAttributes結(jié)構(gòu)的代碼以描述 Live Activity 的靜態(tài)和動(dòng)態(tài)數(shù)據(jù).
使用您定義的
ActivityAttributes
創(chuàng)建開始實(shí)時(shí)活動(dòng)所需的ActivityConfiguration。添加代碼以配置、啟動(dòng)、更新和結(jié)束您的實(shí)時(shí)活動(dòng)。
定義一組靜態(tài)和動(dòng)態(tài)數(shù)據(jù)
在為 Live Activity 創(chuàng)建配置對(duì)象之前,通過實(shí)現(xiàn) ActivityAttributes 來描述 Live Activity 顯示的數(shù)據(jù)。ActivityAttributes 通知系統(tǒng)有關(guān) Live Activity 中出現(xiàn)的靜態(tài)數(shù)據(jù)。您還可以使用 ActivityAttributes 來聲明所需的自定義 Activity.ContentState 類型,該類型描述您的 Live Activity 的動(dòng)態(tài)數(shù)據(jù)。在下面的示例中,PizzaDeliveryAttributes 描述了以下靜態(tài)數(shù)據(jù):訂購(gòu)的比薩餅數(shù)量、客戶需要支付的金額以及訂單號(hào)。請(qǐng)注意代碼如何定義 Activity.ContentState 來封裝動(dòng)態(tài)數(shù)據(jù):送披薩的司機(jī)的姓名和預(yù)計(jì)送達(dá)時(shí)間。此外,該示例定義了類型別名 PizzaDeliveryStatus 以使代碼更具描述性和易于閱讀。
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
}
為您的實(shí)時(shí)活動(dòng)創(chuàng)建配置
添加代碼以使用 ActivityAttributes 結(jié)構(gòu)來描述 Live Activity 中顯示的數(shù)據(jù)后,添加代碼以在小部件實(shí)現(xiàn)中返回 ActivityConfiguration。以下示例使用上一個(gè)示例中的 PizzaDeliveryAttributes 結(jié)構(gòu)來配置您的 Live Activity。
import SwiftUI
import WidgetKit
@main
struct PizzaDeliveryActivityWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
// Create the view 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 views that appear in the Dynamic Island.
// ...
}
}
}
如果您的應(yīng)用已經(jīng)提供小部件,請(qǐng)將 Live Activity 添加到您的 WidgetBundle。如果您沒有 WidgetBundle(例如,如果您只提供一個(gè)小部件),請(qǐng)按照創(chuàng)建小部件擴(kuò)展中的描述創(chuàng)建一個(gè)小部件包,然后將 Live Activity 添加到其中。以下示例顯示了如何使用帶有可用性子句的 if 語句僅在設(shè)備支持 Live Activity 的情況下將 Live Activity 添加到小部件捆綁包中:
@main
struct PizzaDeliveryWidgets: WidgetBundle {
var body: some Widget {
FavoritePizzaWidget()
if #available(iOS 16.1, *) {
PizzaDeliveryLiveActivity()
}
}
}
創(chuàng)建鎖定屏幕視圖
要?jiǎng)?chuàng)建 Live Activity 的用戶界面,您可以在之前創(chuàng)建的小部件擴(kuò)展中使用SwiftUI。與小部件類似,您無需為 Live Activity 提供用戶界面的大小,而是讓系統(tǒng)確定合適的尺寸。
從鎖定屏幕上顯示的視圖開始。以下代碼顯示PizzaDeliveryAttributes
結(jié)構(gòu)使用標(biāo)準(zhǔn) SwiftUI 視圖描述的信息:
@main
struct PizzaDeliveryWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
// Create the view 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 views 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)
}
}
筆記
如果其高度超過 160 點(diǎn),系統(tǒng)可能會(huì)截?cái)噫i定屏幕上的實(shí)時(shí)活動(dòng)。
創(chuàng)建緊湊和最小的視圖
實(shí)時(shí)活動(dòng)出現(xiàn)在支持它的設(shè)備的靈動(dòng)島中。當(dāng)您啟動(dòng)一個(gè) Live Activity 并且它是唯一一個(gè)活躍的 Live Activity 時(shí),緊湊的前導(dǎo)視圖和尾隨視圖一起出現(xiàn),以在 Dynamic Island 中形成一個(gè)有凝聚力的視圖。當(dāng)多個(gè) Live Activity 處于活動(dòng)狀態(tài)時(shí)(無論是來自您的應(yīng)用程序還是來自多個(gè)應(yīng)用程序),系統(tǒng)會(huì)選擇哪些 Live Activity 可見并使用每個(gè)最小視圖顯示兩個(gè):一個(gè)最小視圖顯示為附加到靈動(dòng)島,而另一個(gè)顯示為分離.
筆記
默認(rèn)情況下,Dynamic Island 中的緊湊和最小視圖使用黑色背景顏色和白色文本。使用keylineTint(_:)修改器將可選的色調(diào)應(yīng)用到靈動(dòng)島 - 例如,應(yīng)用青色,如下例所示。
以下示例展示了披薩外賣應(yīng)用程序如何使用標(biāo)準(zhǔn) SwiftUI 視圖提供所需的緊湊和最小視圖:
import SwiftUI
import WidgetKit
@main
struct PizzaDeliveryWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
// Create the view 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 views that appear in the Dynamic Island.
DynamicIsland {
// Create the expanded view.
// ...
} 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)
}
}
}
創(chuàng)建擴(kuò)展視圖
除了緊湊和最小視圖之外,您還必須支持?jǐn)U展視圖。當(dāng)一個(gè)人觸摸并持有一個(gè)緊湊或最小的視圖時(shí),它會(huì)出現(xiàn),并且也會(huì)短暫出現(xiàn)以用于實(shí)時(shí)活動(dòng)更新。當(dāng)您更新實(shí)時(shí)活動(dòng)時(shí),沒有靈動(dòng)島的設(shè)備也會(huì)將擴(kuò)展視圖顯示為橫幅。使用DynamicIslandExpandedRegionPosition指定您希望 SwiftUI 將內(nèi)容放置在何處的詳細(xì)說明。以下示例顯示了披薩外賣應(yīng)用程序如何創(chuàng)建其擴(kuò)展視圖:
@main
struct PizzaDeliveryWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: PizzaDeliveryAttributes.self) { context in
// Create the view 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 views that appear in the Dynamic Island.
DynamicIsland {
// Create the expanded view.
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 view.
// ...
} compactTrailing: {
// Create the compact trailing view.
// ...
} minimal: {
// Create the minimal view.
// ...
}
.keylineTint(.yellow)
}
}
}
筆記
如果靈動(dòng)島的高度超過 160 點(diǎn),系統(tǒng)可能會(huì)截?cái)囔`動(dòng)島中的實(shí)時(shí)活動(dòng)。
為了呈現(xiàn)展開的 Live Activity 中出現(xiàn)的視圖,系統(tǒng)將展開的視圖劃分為不同的區(qū)域。請(qǐng)注意該示例如何返回一個(gè)指定多個(gè)DynamicIslandExpandedRegion 對(duì)象的DynamicIsland。傳遞以下值DynamicIslandExpandedRegionPosition以在展開視圖中的指定位置布置您的內(nèi)容:
center:將內(nèi)容放置在原深感攝像頭下方。
leading:將內(nèi)容沿展開的 Live Activity 的前沿放置在原深感攝像頭旁邊,并在其下方包裹其他內(nèi)容。
trailing:將內(nèi)容放置在 TrueDepth 攝像頭旁邊展開的 Live Activity 的后沿,并在其下方包裹其他內(nèi)容。
bottom:將內(nèi)容置于前導(dǎo)、尾隨和居中內(nèi)容之下。
[圖片上傳失敗...(image-96c63b-1665454932342)]
為了呈現(xiàn)展開的 Live Activity 中出現(xiàn)的內(nèi)容,<u>系統(tǒng)首先確定中心內(nèi)容的寬度,同時(shí)考慮前導(dǎo)和尾隨內(nèi)容的最小寬度</u>。然后系統(tǒng)根據(jù)其垂直位置放置前導(dǎo)和尾隨內(nèi)容并確定其大小。默認(rèn)情況下,前導(dǎo)視圖和尾隨視圖接收相同數(shù)量的水平空間。
[圖片上傳失敗...(image-45ee62-1665454932342)]
您可以通過將優(yōu)先級(jí)傳遞給init(_:priority:content:)初始化程序來告訴系統(tǒng)優(yōu)先考慮DynamicIslandExpandedRegion
視圖之一。系統(tǒng)以動(dòng)態(tài)島的全寬呈現(xiàn)具有最高優(yōu)先級(jí)的視圖。
筆記
如果內(nèi)容太寬而無法出現(xiàn)在 TrueDepth 相機(jī)旁邊的前導(dǎo)位置,請(qǐng)使用belowIfTooWide修飾符來渲染 TrueDepth 相機(jī)下方的前導(dǎo)內(nèi)容。
使用自定義顏色
默認(rèn)情況下,系統(tǒng)使用默認(rèn)的文本原色和最適合用戶鎖定屏幕的 Live Activity 的背景顏色。要設(shè)置自定義色調(diào)顏色,請(qǐng)使用視圖修飾符activityBackgroundTint(_:)。此外,使用activitySystemActionForegroundColor(_:)視圖修飾符自定義允許人們?cè)阪i定屏幕上結(jié)束實(shí)時(shí)活動(dòng)的輔助按鈕的文本顏色。
要設(shè)置自定義背景色調(diào)顏色的半透明,請(qǐng)使用opacity(_:)視圖修改器或指定不透明背景顏色。
筆記
在包括 Always-On Retina 顯示屏的設(shè)備上,系統(tǒng)會(huì)調(diào)暗屏幕以延長(zhǎng)電池壽命,并在鎖定屏幕上呈現(xiàn)實(shí)時(shí)活動(dòng),就像在暗模式下一樣。使用 SwiftUI 的isLuminanceReduced環(huán)境值來檢測(cè) Always On 并使用在 Always On 中看起來很棒的圖像。
在您的應(yīng)用中創(chuàng)建深層鏈接
人們點(diǎn)擊實(shí)時(shí)活動(dòng)來啟動(dòng)您的應(yīng)用程序。為了改善用戶體驗(yàn),您可以使用widgetURL(_:)從鎖定屏幕、緊湊的前導(dǎo)、緊湊的尾隨和最少的視圖創(chuàng)建到您的應(yīng)用程序的深層鏈接。當(dāng)緊湊的前導(dǎo)視圖和尾隨視圖可見時(shí),請(qǐng)確保它們都鏈接到應(yīng)用程序中的同一屏幕。
擴(kuò)展視圖提供了額外的選項(xiàng)來創(chuàng)建應(yīng)用程序的深層鏈接,以便使用 SwiftUI 的Link.例如,披薩外賣應(yīng)用程序可能包含兩個(gè) SwiftUI 視圖。一個(gè)視圖可以在應(yīng)用程序中打開當(dāng)前送貨的地圖,第二個(gè)視圖可以打開一個(gè)屏幕,讓人們可以打電話給送披薩的人。
確保現(xiàn)場(chǎng)活動(dòng)可用
現(xiàn)場(chǎng)活動(dòng)僅在 iPhone 上可用。如果您的應(yīng)用可在多個(gè)平臺(tái)上使用并提供小部件擴(kuò)展,請(qǐng)確保實(shí)時(shí)活動(dòng)在運(yùn)行時(shí)可用。此外,用戶可以在“設(shè)置”應(yīng)用中選擇停用應(yīng)用的實(shí)時(shí)活動(dòng)。
要查看 Live Activity 是否可用以及用戶是否允許您的應(yīng)用使用 Live Activity:
- 使用areActivitiesEnabled同步確定是否在您的應(yīng)用中顯示用戶界面以啟動(dòng) Live Activity。
- 通過使用activityEnablementUpdates觀察流中的任何用戶授權(quán)更改來接收異步用戶授權(quán)更新并相應(yīng)地響應(yīng)它們。
筆記
一個(gè)應(yīng)用可以啟動(dòng)多個(gè) Live Activity,而一個(gè)設(shè)備可以從多個(gè)應(yīng)用運(yùn)行 Live Activity。除了確保 Live Activity 可用之外,在開始、更新或結(jié)束 Live Activity 時(shí)始終優(yōu)雅地處理任何錯(cuò)誤。例如,啟動(dòng) Live Activity 可能會(huì)失敗,因?yàn)橛脩舻脑O(shè)備可能已達(dá)到其活動(dòng) Live Activity 的限制。
開始現(xiàn)場(chǎng)活動(dòng)
當(dāng)應(yīng)用程序在前臺(tái)時(shí),您可以在應(yīng)用程序代碼中使用request(attributes:contentState:pushType:)函數(shù)啟動(dòng) Live Activity。它將您創(chuàng)建的屬性和內(nèi)容狀態(tài)作為參數(shù)來提供顯示在 Live Activity 中的初始值,并告訴系統(tǒng)哪些數(shù)據(jù)是動(dòng)態(tài)的。如果您實(shí)施遠(yuǎn)程推送通知來更新 Live Activity,還需要提供 pushType
參數(shù)。
以下代碼示例從前面的示例中為披薩外賣應(yīng)用啟動(dòng)了一個(gè)新的 Live Activity:
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")
do {
deliveryActivity = try Activity.request(attributes: activityAttributes, contentState: initialContentState)
print("Requested a pizza delivery Live Activity \(String(describing: deliveryActivity?.id)).")
} catch (let error) {
print("Error requesting pizza delivery Live Activity \(error.localizedDescription).")
}
請(qǐng)注意上面的代碼片段如何不傳遞pushType
參數(shù)并在不使用遠(yuǎn)程推送通知更新其內(nèi)容的情況下啟動(dòng) Live Activity。它還將返回的 Live Activity 對(duì)象存儲(chǔ)在可用于更新和結(jié)束 Live Activity 的deliveryActivity
屬性中。有關(guān)使用遠(yuǎn)程推送通知更新您的實(shí)時(shí)活動(dòng)的更多信息,請(qǐng)參閱使用遠(yuǎn)程推送通知更新和結(jié)束您的實(shí)時(shí)活動(dòng)。
筆記
您只能在應(yīng)用程序處于前臺(tái)時(shí)從應(yīng)用程序啟動(dòng)實(shí)時(shí)活動(dòng)。但是,您可以在應(yīng)用程序在后臺(tái)運(yùn)行時(shí)更新或結(jié)束 Live Activity - 例如,通過使用Background Tasks。
更新實(shí)時(shí)活動(dòng)
當(dāng)您從應(yīng)用程序啟動(dòng) Live Activity 時(shí),使用您在啟動(dòng) Live Activity 時(shí)收到的Activity對(duì)象的update(using:)函數(shù)更新顯示在 Live Activity 中的數(shù)據(jù)。要檢索應(yīng)用程序的活動(dòng)實(shí)時(shí)活動(dòng),請(qǐng)使用activities.
例如,披薩配送應(yīng)用程序可以更新顯示配送狀態(tài)的 Live Activity,其中包含新的配送時(shí)間和新的司機(jī)。它還可以使用update(using:alertConfiguration:)函數(shù)在 iPhone 和 Apple Watch 上顯示警報(bào),告知人們新的 Live Activity 內(nèi)容,如下例所示:
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)
await deliveryActivity?.update(using: updatedDeliveryStatus, alertConfiguration: alertConfiguration)
筆記
更新數(shù)據(jù)的大小不能超過 4KB。
在 Apple Watch 上,系統(tǒng)將title
和body
屬性用于alert
。在 iPhone 上,系統(tǒng)不會(huì)顯示常規(guī)alert
,而是顯示靈動(dòng)島中展開的實(shí)時(shí)活動(dòng)。在不支持靈動(dòng)島的設(shè)備上,系統(tǒng)會(huì)在主屏幕上顯示一個(gè)橫幅,該橫幅使用您的實(shí)時(shí)活動(dòng)的擴(kuò)展視圖。
動(dòng)畫內(nèi)容更新
當(dāng)您定義 Live Activity 的用戶界面時(shí),系統(tǒng)會(huì)忽略任何動(dòng)畫修改器,例如withAnimation(::),和animation(_:value:),而是使用系統(tǒng)的動(dòng)畫時(shí)間。但是,當(dāng) Live Activity 的動(dòng)態(tài)內(nèi)容發(fā)生變化時(shí),系統(tǒng)會(huì)執(zhí)行一些動(dòng)畫。文本視圖通過模糊的內(nèi)容過渡動(dòng)畫內(nèi)容變化,并且系統(tǒng)為圖像和 SF 符號(hào)動(dòng)畫內(nèi)容過渡。如果您根據(jù)內(nèi)容或狀態(tài)更改從用戶界面添加或刪除視圖,視圖會(huì)淡入淡出。使用以下視圖轉(zhuǎn)換來配置這些內(nèi)置轉(zhuǎn)換:opacity、move(edge:)、slide、push(from:)或它們的組合。此外,使用numericText(countsDown:)請(qǐng)求計(jì)時(shí)器文本的動(dòng)畫。
筆記
在包含 Always On Retina 顯示屏的設(shè)備上,系統(tǒng)不會(huì)執(zhí)行動(dòng)畫以保持 Always On 的電池壽命。確保在動(dòng)畫內(nèi)容更改之前使用 SwiftUI 的isLuminanceReduced環(huán)境值來檢測(cè) Always On。
從您的應(yīng)用程序中結(jié)束實(shí)時(shí)活動(dòng)
始終在關(guān)聯(lián)的任務(wù)或?qū)崟r(shí)事件結(jié)束后結(jié)束實(shí)時(shí)活動(dòng)。已結(jié)束的實(shí)時(shí)活動(dòng)將保留在鎖定屏幕上,直到用戶將其刪除或系統(tǒng)自動(dòng)將其刪除。自動(dòng)刪除取決于您為函數(shù)end(using:dismissalPolicy:)提供的解雇策略。此外,始終包含更新的Activity.ContentState以確保實(shí)時(shí)活動(dòng)在結(jié)束后顯示最新和最終的內(nèi)容更新。這很重要,因?yàn)閷?shí)時(shí)活動(dòng)可以在鎖定屏幕上保持可見一段時(shí)間。
以下示例顯示了披薩外賣應(yīng)用程序如何結(jié)束一個(gè)實(shí)時(shí)活動(dòng),該活動(dòng)顯示比薩送達(dá)時(shí)訂單的交付狀態(tài):
let finalDeliveryStatus = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Anne Johnson", deliveryTimer: Date.now...Date())
Task {
await deliveryActivity?.end(using:finalDeliveryStatus, dismissalPolicy: .default)
}
上面的示例使用default解雇政策。因此,實(shí)時(shí)活動(dòng)結(jié)束后會(huì)在鎖定屏幕上顯示一段時(shí)間,以允許用戶瀏覽他們的手機(jī)以查看最新信息。用戶可以隨時(shí)選擇移除 Live Activity,或者系統(tǒng)在活動(dòng)結(jié)束四小時(shí)后自動(dòng)移除。
要立即刪除從鎖定屏幕結(jié)束的實(shí)時(shí)活動(dòng),請(qǐng)使用immediate。或者,用于after(_:)`指定四小時(shí)窗口內(nèi)的日期。雖然您可以提供任何日期,但系統(tǒng)會(huì)在給定日期之后或在實(shí)時(shí)活動(dòng)結(jié)束后四個(gè)小時(shí)后刪除已結(jié)束的實(shí)時(shí)活動(dòng) - 以先到者為準(zhǔn)。
用戶可以隨時(shí)從鎖定屏幕中刪除您的實(shí)時(shí)活動(dòng)。這會(huì)結(jié)束您的 Live Activity,但不會(huì)結(jié)束或取消用戶啟動(dòng) Live Activity 的操作。例如,用戶可以從鎖定屏幕中刪除他們的披薩外賣的實(shí)時(shí)活動(dòng),但這不會(huì)取消披薩訂單。當(dāng)用戶或系統(tǒng)刪除實(shí)時(shí)活動(dòng)時(shí)ActivityState更改為ActivityState.dismissed。
使用遠(yuǎn)程推送通知更新或結(jié)束您的實(shí)時(shí)活動(dòng)
除了使用 ActivityKit 從您的應(yīng)用程序更新和結(jié)束實(shí)時(shí)活動(dòng)之外,您還可以使用從服務(wù)器發(fā)送到 Apple 推送通知服務(wù) (APN) 的遠(yuǎn)程推送通知更新或結(jié)束實(shí)時(shí)活動(dòng)。要了解有關(guān)使用遠(yuǎn)程推送通知更新您的實(shí)時(shí)活動(dòng)的更多信息,請(qǐng)參閱使用遠(yuǎn)程推送通知更新和結(jié)束您的實(shí)時(shí)活動(dòng)。
跟蹤更新
當(dāng)您啟動(dòng) Live Activity 時(shí),ActivityKit 會(huì)返回一個(gè)Activity對(duì)象。除了唯一標(biāo)識(shí)每個(gè)活動(dòng)的id之外,Activity還提供觀察內(nèi)容狀態(tài)、活動(dòng)狀態(tài)和推送令牌更新的序列。使用相應(yīng)的序列在您的應(yīng)用中接收更新,使您的應(yīng)用和 Live Activity 保持同步,并響應(yīng)更改的數(shù)據(jù):
要觀察正在進(jìn)行的 Live Activity 的狀態(tài)——例如,確定它是處于活動(dòng)狀態(tài)還是已經(jīng)結(jié)束——使用activityStateUpdates
要觀察 Live Activity 動(dòng)態(tài)內(nèi)容的變化,請(qǐng)使用contentState
要觀察 Live Activity 的推送令牌的變化,請(qǐng)使用pushTokenUpdates
獲取活動(dòng)列表
您的應(yīng)用可以啟動(dòng)多個(gè) Live Activity。例如,體育應(yīng)用程序可能允許用戶為他們感興趣的每個(gè)現(xiàn)場(chǎng)體育比賽啟動(dòng)Live Activity。如果您的應(yīng)用程序啟動(dòng)多個(gè)Live Activity,請(qǐng)使用activityUpdates函數(shù)獲取有關(guān)您的應(yīng)用程序正在進(jìn)行的Live Activity的通知。跟蹤正在進(jìn)行的 Live Activity 以確保您的應(yīng)用程序的數(shù)據(jù)與 ActivityKit 跟蹤的活動(dòng) Live Activity 同步。
以下代碼段顯示了披薩外賣應(yīng)用程序如何檢索正在進(jìn)行的活動(dòng)列表:
// Fetch all ongoing pizza delivery Live Activities.
for await activity in Activity<PizzaDeliveryAttributes>.activityUpdates {
print("Pizza delivery details: \(activity.attributes)")
}
獲取所有活動(dòng)的另一個(gè)用例是維護(hù)正在進(jìn)行的實(shí)時(shí)活動(dòng),并確保您不會(huì)讓任何活動(dòng)持續(xù)運(yùn)行超過需要的時(shí)間。例如,系統(tǒng)可能會(huì)停止您的應(yīng)用程序,或者您的應(yīng)用程序可能會(huì)在 Live Activity 處于活動(dòng)狀態(tài)時(shí)崩潰。當(dāng)應(yīng)用下次啟動(dòng)時(shí),檢查是否有任何活動(dòng)仍處于活動(dòng)狀態(tài),更新應(yīng)用存儲(chǔ)的 Live Activity 數(shù)據(jù),并結(jié)束任何不再相關(guān)的 Live Activity。
也可以看看
現(xiàn)場(chǎng)活動(dòng)實(shí)施
使用遠(yuǎn)程推送通知更新和結(jié)束您的實(shí)時(shí)活動(dòng)
當(dāng)您開始實(shí)時(shí)活動(dòng)時(shí)接收推送令牌,并使用它通過遠(yuǎn)程推送通知更新或結(jié)束您的實(shí)時(shí)活動(dòng)。
class Activity 用于啟動(dòng)、更新和結(jié)束實(shí)時(shí)活動(dòng)的對(duì)象。