原文地址:官方文檔地址
概述
實時活動在iPhone鎖定屏幕上顯示和更新應用程序的最新數(shù)據(jù)夭委。這允許人們一目了然地看到他們最關心的實時信息煮岁。
重要的
Live Activities和ActivityKit將不會包含在最初公開發(fā)布的iOS 16版本中牢裳,但將在今年晚些時候的更新中公開發(fā)布便瑟。一旦它們公開發(fā)布,您可以將帶有Live Activities的應用程序提交到App Store。
要提供實時活動濒募,請向現(xiàn)有小部件擴展添加代碼,或者如果您的應用程序尚未包含新的小部件擴展圾结,則創(chuàng)建新的小部件擴展瑰剃。Live Activities使用WidgetKit功能和SwiftUI作為鎖定屏幕上的用戶界面。ActivityKit的作用是處理每個實時活動的生命周期:您可以使用其API請求筝野、更新和結束實時活動晌姚。
/現(xiàn)場活動僅在iPhone上提供。/
查看“實時活動”要求和限制
除非您的應用程序或用戶明確終止歇竟,否則實時活動最多可以活動八小時挥唠。在此限制之后,如果用戶或您的應用程序尚未結束實時活動焕议,系統(tǒng)會自動結束活動宝磨。在這個結束狀態(tài)下,實時活動在鎖定屏幕上最多可延長四個小時盅安,然后系統(tǒng)將其刪除唤锉。用戶也可以選擇刪除它。因此别瞭,實時活動在鎖定屏幕上最多停留12小時窿祥。
有關結束實時活動的更多信息,請參閱下面的“從應用程序內(nèi)結束實時活動”蝙寨。
每個實時活動都在自己的沙盒中運行晒衩,與小部件不同,它無法訪問網(wǎng)絡或接收位置更新墙歪。要更新活動實時活動的動態(tài)數(shù)據(jù)听系,請使用應用程序中的ActivityKit框架,或允許您的實時活動接收遠程推送通知箱亿,如下面的“使用遠程推送通知更新或結束實時活動”部分中所述。
活動套件更新和遠程推送通知更新的動態(tài)數(shù)據(jù)大小不得超過4KB弃秆。
為您的應用程序添加對實時活動的支持
描述實時活動用戶界面的代碼是應用程序小部件擴展的一部分届惋。如果您已經(jīng)在應用程序中提供了小部件,您可以將實時活動的用戶界面代碼添加到現(xiàn)有的小部件擴展中菠赚,并可能能夠在小部件和實時活動之間重用代碼脑豹。然而,盡管Live Activities利用了WidgetKit的功能衡查,但它們不是小部件瘩欺。與用于更新小部件用戶界面的時間機制不同,您可以使用ActivityKit或遠程推送通知從應用程序更新實時活動。
您可以創(chuàng)建一個小部件擴展來采用實時活動俱饿,而無需提供小部件歌粥。但是,請考慮同時提供小部件和實時活動拍埠,讓人們在主屏幕和鎖定屏幕上添加可瀏覽的信息和個人觸摸失驶。
要為您的應用程序添加對實時活動的支持:
1、如果您尚未向應用程序添加小部件擴展枣购,請創(chuàng)建一個小部件擴展嬉探。有關創(chuàng)建小部件擴展的更多信息,請參閱WidgetKit和創(chuàng)建小部件擴展棉圈。
2涩堤、打開應用程序的Info.plist文件,并添加一個條目分瘾,其鍵為布爾類型為NSSupportsLiveActivities胎围,值為YES。
3芹敌、在您的代碼中痊远,為您的實時活動定義一組ActivityAttributes和Activity.ContentState。您將使用它們開始氏捞、更新和結束實時活動碧聪。
4、添加代碼以創(chuàng)建小部件液茎,并在小部件實現(xiàn)中返回ActivityConfiguration逞姿,如下例所示。
5捆等、如果您的應用程序已經(jīng)包含小部件滞造,請將您的實時活動添加到您的WidgetBundle中,或按照創(chuàng)建小部件擴展中所述創(chuàng)建一個栋烤。如果您只添加小部件擴展以支持實時活動谒养,請?zhí)^此步驟。
6明郭、添加代碼以開始买窟、更新和結束實時活動,并創(chuàng)建其用戶界面薯定,如下所述始绍。
7、要測試您的實時活動话侄,請在模擬器中運行您的應用程序亏推,并從應用程序的用戶界面啟動實時活動学赛。
以下代碼片段返回一個活動配置,以將包含交付信息的實時活動添加到披薩交付應用程序中:
import ActivityKit
import SwiftUI
import WidgetKit
struct PizzaDeliveryAttributes: ActivityAttributes {
public typealias PizzaDeliveryStatus = ContentState
public struct ContentState: Codable, Hashable {
var driverName: String
var estimatedDeliveryTime: Date
}
var numberOfPizzas: Int
var totalAmount: String
}
struct PizzaDeliveryActivityWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(attributesType: PizzaDeliveryAttributes.self) { context in
// Create the Lock Screen user interface for your Live Activity.
// ...
}
}
}
要創(chuàng)建 ActivityConfiguration吞杭,您可以提供 ActivityAttributes盏浇,告知系統(tǒng)實時活動中顯示的靜態(tài)數(shù)據(jù)。使用ActivityAttributes還聲明所需的自定義Activity.ContentState類型篇亭,該類型描述了您實時活動的動態(tài)數(shù)據(jù)缠捌。在上面的示例中,PizzaDeliveryAttributes描述了以下靜態(tài)數(shù)據(jù):訂購的披薩數(shù)量和客戶需要支付的金額译蒂。注意代碼如何定義Activity.ContentState來封裝動態(tài)數(shù)據(jù):交付披薩的驅動程序的名稱和預計交貨時間曼月。它定義了類型別名PizzaDeliveryStatus,使代碼更具描述性和易于閱讀性柔昼。
創(chuàng)建實時活動的用戶界面
要創(chuàng)建 Live Activity 的用戶界面哑芹,請在之前創(chuàng)建的小組件擴展中使用 SwiftUI。與小部件類似捕透,您不提供實時活動用戶界面的大小聪姿,而是讓系統(tǒng)確定適當?shù)某叽纭?/p>
如果活動高度超過160點,系統(tǒng)可能會截斷實時活動乙嘀。
以下代碼顯示PizzaDeliveryAttributes結構使用標準SwiftUI視圖描述的信息:
struct PizzaDeliveryActivityWidget: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(attributesType: PizzaDeliveryAttributes.self) { context in
// Create the user interface for your Live Activity that appears on the Lock Screen.
VStack {
Text("\(context.attributes.numberOfPizzas) ordered for \(context.attributes.totalAmount).")
HStack {
Text("\(context.state.driverName) is on their way with your pizza!")
Text(context.state.estimatedDeliveryTime, style: .timer)
}
}.activityBackgroundTint(Color.cyan)
}
}
}
默認情況下末购,系統(tǒng)對文本使用默認的白色,對您的實時活動使用最適合用戶鎖定屏幕的背景顏色虎谢。要設置自定義色調顏色盟榴,請使用活動BackgroundTint(:)視圖修飾符,如上例所示婴噩。要設置自定義背景色調顏色的半透明性擎场,請使用不透明度(:)視圖修飾符〖该В或者迅办,使用ZStack指定不透明的背景顏色:
// Create the Lock Screen user interface for your Live Activity.
ZStack {
Color.cyan
VStack {
Text("\(context.attributes.numberOfPizzas) ordered for \(context.attributes.totalAmount).")
HStack {
Text("\(context.state.driverName) is on their way with your pizza!")
Text(context.state.estimatedDeliveryTime, style: .timer)
}
}
}.activitySystemActionForegroundColor(Color.cyan)
此外,您可以自定義輔助按鈕的顏色章蚣,允許用戶使用activitySystemActionForegroundColor(_:)視圖修飾符結束實時活動站欺,如上例所示。
確毕舜梗現(xiàn)場活動可用
現(xiàn)場活動僅在iPhone上提供矾策。如果您的應用程序在多個平臺上可用,并提供小部件擴展洒忧,請確保實時活動在運行時可用蝴韭。此外够颠,用戶可以選擇在iPhone上的設置應用程序中停用應用程序的實時活動熙侍。
要查看實時活動是否可用,以及用戶是否允許您的應用程序使用實時活動:
使用 areActivitiesEnabled同步確定是否在應用程序中顯示用戶界面以開始實時活動。
通過使用 activityEnablementUpdates 流觀察任何用戶授權更改蛉抓,接收有關用戶授權的異步更新庆尘,并相應地響應它們。
每個應用程序可以啟動多個實時活動巷送,一臺設備可以從多個應用程序運行實時活動驶忌。然而,用戶的設備可能已經(jīng)達到了活躍的實時活動極限笑跛。除了確保實時活動可用外付魔,在開始、更新或結束實時活動時飞蹂,請務必優(yōu)雅地處理任何錯誤几苍。
開始現(xiàn)場活動
當應用程序處于前臺時,您可以使用request(attributes:contentState:pushType:)功能在應用程序的代碼中開始實時活動陈哑。您創(chuàng)建的屬性和內(nèi)容狀態(tài)作為參數(shù)妻坝,以提供實時活動中顯示的初始值,并告訴系統(tǒng)哪些數(shù)據(jù)是動態(tài)的惊窖。如果您實現(xiàn)遠程推送通知以更新實時活動刽宪,也請?zhí)峁﹑ushType參數(shù)。
以下代碼示例從前面的示例中為披薩配送應用程序啟動了一個新的實時活動:
let pizzaDeliveryAttributes = PizzaDeliveryAttributes(numberOfPizzas: 42, totalAmount:"$420,-")
// Estimated delivery time is one hour from now.
let initialContentState = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Bill James", estimatedDeliveryTime: Date().addingTimeInterval(60 * 60))
do {
let deliveryActivity = try Activity<PizzaDeliveryAttributes>.request(
attributes: pizzaDeliveryAttributes,
contentState: initialContentState,
pushType: nil)
print("Requested a pizza delivery Live Activity \(deliveryActivity.id)")
} catch (let error) {
print("Error requesting pizza delivery Live Activity \(error.localizedDescription)")
}
注意上面的片段如何將零傳遞給pushType參數(shù)界酒,并在不使用遠程推送通知來更新其內(nèi)容的情況下開始實時活動圣拄。有關使用遠程推送通知更新實時活動的更多信息,請參閱下面的“使用遠程推送通知更新或結束實時活動”部分盾计。
您只能在應用程序處于前臺時從其啟動實時活動售担。但是,您可以在應用程序在后臺運行時更新或結束實時活動——例如署辉,通過使用后臺任務族铆。
更新實時活動
當您從應用程序開始實時活動時,請使用您在開始實時活動時收到的健身記錄對象上的更新(使用:)功能更新實時活動上顯示的數(shù)據(jù)哭尝。要檢索應用程序的活躍實時活動哥攘,請使用活動。
例如材鹦,披薩送貨應用程序可以更新實時活動逝淹,顯示送貨狀態(tài),包括新的送貨時間和新的驅動程序:
let updatedDeliveryStatus = PizzaDeliveryStatus(driverName: "Anne Johnson", estimatedDeliveryTime: Date().addingTimeInterval(60 * 60))
do {
try await deliveryActivity.update(using: updatedDeliveryStatus)
} catch(let error) {
print("Error updating activity \(error.localizedDescription)")
}
更新數(shù)據(jù)的大小不能超過4KB桶唐。
動畫內(nèi)容更新
當您定義實時活動的用戶界面時栅葡,系統(tǒng)會忽略任何動畫修飾符——例如withAnimation(::)和動畫(_:value:)——而是使用系統(tǒng)的動畫計時。然而尤泽,當實時活動的動態(tài)內(nèi)容發(fā)生變化時欣簇,系統(tǒng)會執(zhí)行一些動畫规脸。文本視圖通過模糊的內(nèi)容轉換為內(nèi)容更改添加動畫效果,系統(tǒng)為圖像和 SF 符號的內(nèi)容轉換添加動畫效果熊咽。如果您根據(jù)內(nèi)容或狀態(tài)更改從用戶界面中添加或刪除視圖莫鸭,視圖會淡入和淡出。使用以下視圖過渡來配置這些內(nèi)置過渡:不透明度横殴、移動(邊緣:)被因、滑動、推送(從:)或組合衫仑。此外梨与,使用numericText(countsDown:)請求計時器文本的動畫。
從您的應用程序內(nèi)結束實時活動
請務必在相關任務或現(xiàn)場活動結束后結束現(xiàn)場活動文狱。已結束的實時活動仍保留在鎖定屏幕上蛋欣,直到用戶刪除它或系統(tǒng)自動刪除它。自動刪除取決于您最后提供的解雇策略(使用:dismissalPolicy:)函數(shù)如贷。
以下示例顯示了披薩送貨應用程序將如何結束實時活動陷虎,該活動顯示披薩交付時訂單的送貨狀態(tài):
let updatedDeliveryStatus = PizzaDeliveryStatus(driverName: "Anne Johnson", estimatedDeliveryTime: Date())
do {
try await deliveryActivity.end(using: updatedDeliveryStatus, dismissalPolicy: .default)
} catch(let error) {
print("Error ending activity \(error.localizedDescription)")
}
上面的示例對解雇策略使用默認值。因此杠袱,實時活動在鎖定屏幕上顯示一段時間尚猿,以便用戶瀏覽手機以查看最新信息。用戶可以選擇隨時刪除已結束的實時活動楣富,或者系統(tǒng)會在四小時后自動刪除它凿掂。
要立即從鎖定屏幕中刪除結束的實時活動,請使用立即纹蝴∽或者,使用 after(_:) 在四小時內(nèi)指定日期塘安。雖然您可以提供任何日期糠涛,但系統(tǒng)會在給定日期之后或從實時活動結束之日起四小時后刪除結束的實時活動,以先到者為準兼犯。
用戶可以隨時從鎖定屏幕中刪除您的實時活動忍捡。這會結束您的實時活動,但它不會結束或取消開始活動的用戶操作切黔。例如砸脊,用戶可以從鎖定屏幕中刪除披薩送貨的實時活動,但這不會取消披薩訂單纬霞。
通過遠程推送通知更新或結束實時活動
除了從您的應用程序更新和結束實時活動外凌埂,還可以通過從服務器發(fā)送到Apple推送通知服務(APN)的遠程推送通知來更新或結束實時活動。接收遠程推送通知以更新實時活動類似于您使用它們顯示應用程序通知的方式诗芜。您使用用戶通知框架來請求使用通知的權限瞳抓。您還必須設置遠程通知服務器秒紧。此任務對于實時活動與在用戶設備上顯示為通知的遠程推送通知相同。
如果您是遠程推送通知的新手挨下,請查看用戶通知框架的文檔。確保您閱讀了使用APN注冊應用程序和請求使用通知的權限脐湾,并按照用戶通知文檔所述計劃實施遠程通知服務器的時間臭笆。
要使用遠程推送通知來更新您的實時活動,請首先將推送通知功能添加到您的應用程序中秤掌,如使用APN注冊您的應用程序中所述愁铺。請注意,您不必為實時活動注冊ForRemoteNotifications()注冊遠程推送通知闻鉴。相反茵乱,請使用ActivityKit獲取以下概述的推送令牌。
要通過推送通知更新或結束實時活動:
1孟岛、在應用程序中啟動實時活動瓶竭,并確保將pushType參數(shù)傳遞給request(attributes:contentState:pushType:)函數(shù)。
2渠羞、成功啟動實時活動后斤贰,將活動的pushToken發(fā)送到推送通知服務器,并使用它向實時活動發(fā)送遠程推送通知次询。
3荧恍、如果您尚未實現(xiàn)自己的遠程推送通知服務器,請創(chuàng)建一個服務器應用程序屯吊,使用APN發(fā)送遠程推送通知送巡。
4、使用存儲在服務器上的推送令牌向實時活動發(fā)送推送通知盒卸。您必須設置內(nèi)容狀態(tài)鍵的字段骗爆,以匹配您的自定義活動。內(nèi)容狀態(tài)類型蔽介,以確保系統(tǒng)可以解碼JSON有效負載并更新實時活動淮腾。
5、要更新實時活動屉佳,請設置要更新的有效載荷事件密鑰的值谷朝。要結束現(xiàn)場活動,請將其設置為結束武花。
6圆凰、使用pushTokenUpdates觀察活動推送令牌的更改,將任何新的推送令牌發(fā)送到您的服務器体箕,并使服務器上的舊令牌無效专钉。
7挑童、當您的實時活動結束時,使服務器上的推送令牌無效跃须。
要測試模擬器中實時活動的遠程推送通知站叼,請使用配備Apple T2安全芯片的Mac機型或運行macOS 13或更高版本的搭載Apple芯片的Mac。
以下有效負載更新了披薩送貨應用程序的司機姓名和交貨時間菇民。注意內(nèi)容狀態(tài)的內(nèi)容如何與之前示例中自定義PizzaDeliveryStatus類型的屬性匹配尽楔。
{
"aps": {
"timestamp": 1650998941,
"event": "update",
"content-state": {
"driverName": "Anne Johnson",
"estimatedDeliveryTime": 1659416400
}
}
}
跟蹤更新
如上圖所示,當您開始實時活動時第练,ActivityKit將返回一個活動對象阔馋。除了唯一標識每個活動的id屬性外,活動還提供了觀察內(nèi)容狀態(tài)娇掏、活動狀態(tài)和推送令牌更新的序列呕寝。使用相應的順序在應用程序中接收更新,保持應用程序和實時活動同步婴梧,并響應更改的數(shù)據(jù):
要觀察正在進行的實時活動的狀態(tài)——例如下梢,確定它是活躍的還是已經(jīng)結束的——請使用 activityStateUpdates。
要觀察實時活動動態(tài)內(nèi)容的變化塞蹭,請使用contentState怔球。
要觀察實時活動的推送令牌的變化,請使用pushTokenUpdates浮还。
獲取活動列表
您的應用程序可以啟動多個實時活動竟坛。例如,體育應用程序可能允許用戶為他們感興趣的每個現(xiàn)場體育游戲開始現(xiàn)場活動钧舌。如果您的應用程序啟動多個實時活動担汤,請使用活動更新功能獲取應用程序的所有正在進行的活動,以確保應用程序的數(shù)據(jù)與ActivityKit跟蹤的活動實時活動同步洼冻。
以下片段顯示了披薩配送應用程序如何檢索正在進行的活動列表:
// Fetch all ongoing pizza delivery activities.
let activityStream = Activity<PizzaDeliveryAttributes>.activityUpdates()
for await activity in activityStream {
print("Pizza delivery details: \(activity.description)")
}
獲取所有活動的另一個用例是維護正在進行的實時活動崭歧,并確保您不會使任何活動運行的時間超過需要。例如撞牢,系統(tǒng)可能會停止您的應用程序率碾,或者您的應用程序可能會在實時活動處于活動狀態(tài)時崩潰。當應用程序下次啟動時屋彪,檢查是否有任何活動仍在活動所宰,更新應用程序存儲的實時活動數(shù)據(jù),并結束任何不再相關的實時活動畜挥。