iOS16靈動島和鎖屏實時活動

使用實時活動顯示實時數(shù)據(jù)

提供實時活動拓哟,在靈動島和鎖定屏幕上顯示您的應(yīng)用程序的最新數(shù)據(jù)。

概述

實時活動在 iPhone 鎖定屏幕和靈動島中顯示您的應(yīng)用程序的最新數(shù)據(jù)唁桩。這使人們可以一目了然地看到實時信息涛碑。

要提供實時活動渊鞋,請將代碼添加到您現(xiàn)有的小部件擴展或創(chuàng)建一個新的小部件擴展(如果您的應(yīng)用尚未包含)胀莹。Live Activity 使用WidgetKit功能和SwiftUI繪制用戶界面基跑。ActivityKit 的作用是處理每個 Live Activity 的生命周期:您使用它的 API 來請求、更新和結(jié)束 Live Activity描焰。

筆記
現(xiàn)場活動僅在 iPhone 上可用媳否。

要提供實時活動( Live Activity)代碼需要添加到小組件中(iOS14 以后的widget)使用WidgetKit功能,使用SwiftUI繪制界面荆秦。iOS16新增了ActivityKit篱竭,其作用是處理每個 Live Activity 的生命周期:您使用它的 API 來請求、更新和結(jié)束 Live Activity步绸。

查看實時活動要求和限制

除非您的應(yīng)用程序或用戶結(jié)束它掺逼,否則 Live Activity 最多可以處于活動狀態(tài)八小時。超過此限制瓤介,系統(tǒng)自動結(jié)束吕喘。當(dāng) Live Activity 結(jié)束時,系統(tǒng)會立即將其從 Dynamic Island 中移除惑朦。但是兽泄,實時活動會一直保留在鎖定屏幕上漓概,直到用戶將其刪除或系統(tǒng)將其刪除前最多四個小時(以先到者為準(zhǔn))漾月。因此,實時活動會在鎖定屏幕上最多保留十二小時胃珍。

有關(guān)結(jié)束 Live Activity 的更多信息梁肿,請參閱下面的“在您的應(yīng)用內(nèi)結(jié)束 Live Activity”。

每個 Live Activity 在自己的沙箱中運行觅彰,并且 - 與小部件不同 - 它無法訪問網(wǎng)絡(luò)或接收位置更新吩蔑。要更新活動 Live Activity 的動態(tài)數(shù)據(jù),請在您的應(yīng)用程序中使用 ActivityKit 框架或允許您的 Live Activity 接收遠(yuǎn)程推送通知填抬,如使用遠(yuǎn)程推送通知更新和結(jié)束您的 Live Activity 中所述烛芬。

筆記
ActivityKit 更新和遠(yuǎn)程推送通知更新的更新動態(tài)數(shù)據(jù)大小不能超過 4KB。

實時活動針對鎖定屏幕和靈動島提供不同的視圖。鎖定屏幕視圖出現(xiàn)在所有設(shè)備上赘娄。支持靈動島的設(shè)備使用以下視圖顯示實時活動:靈動島的緊湊前視圖仆潮、緊湊尾視圖、最小視圖和擴展視圖遣臼。
當(dāng)人在靈動島中觸摸并持有緊湊或最小視圖以及實時活動更新時性置,會出現(xiàn)擴展視圖累澡。在不支持靈動島的解鎖設(shè)備上均芽,展開的視圖顯示為實時活動更新的橫幅饶米。
為確保系統(tǒng)可以在每個位置顯示您的 Live Activity续扔,您必須支持所有視圖端衰。

為您的應(yīng)用添加對實時活動的支持

描述 Live Activity 用戶界面的代碼是應(yīng)用的小部件擴展的一部分篓跛。如果您已經(jīng)在應(yīng)用程序中提供小部件圃庭,則可以將 Live Activity 的用戶界面代碼添加到現(xiàn)有的小部件擴展中吏颖,并且可以在小部件和 Live Activity 之間重用代碼蝙眶。然而凰萨,盡管 Live Activity 利用了 WidgetKit 的功能,但它們并不是小部件械馆。與您用于更新小部件用戶界面的時間線機制相比胖眷,您可以使用 ActivityKit 或遠(yuǎn)程推送通知從您的應(yīng)用程序更新實時活動。

筆記
您可以創(chuàng)建一個小部件擴展來采用實時活動霹崎,而無需提供小部件珊搀。但是,請考慮同時提供小部件和實時活動尾菇,以允許人們在主屏幕和鎖定屏幕上添加可瀏覽的信息和個人風(fēng)格境析。

為您的應(yīng)用添加對實時活動的支持:

  1. 如果您還沒有向您的應(yīng)用程序添加一個小部件擴展,請創(chuàng)建一個小部件擴展派诬。有關(guān)創(chuàng)建小部件擴展的更多信息劳淆,請參閱WidgetKit創(chuàng)建小部件擴展

  2. 打開應(yīng)用程序的 Info.plist 文件默赂,添加 Supports Live Activities 條目沛鸵,并將其布爾值設(shè)置為 YES±掳耍或者曲掰,將 Info.plist 文件作為源代碼打開,添加鍵 NSSupportsLiveActivities奈辰,然后將類型設(shè)置為布爾值并將其值設(shè)置為 YES栏妖。如果您的項目沒有Info.plist 文件,請將條目添加到您的 iOS 應(yīng)用程序目標(biāo)的自定義 iOS 目標(biāo)屬性列表中奖恰。

  3. 添加定義ActivityAttributes結(jié)構(gòu)的代碼以描述 Live Activity 的靜態(tài)和動態(tài)數(shù)據(jù).

  4. 使用您定義的 ActivityAttributes創(chuàng)建開始實時活動所需的ActivityConfiguration吊趾。

  5. 添加代碼以配置宛裕、啟動、更新和結(jié)束您的實時活動论泛。

定義一組靜態(tài)和動態(tài)數(shù)據(jù)

在為 Live Activity 創(chuàng)建配置對象之前续滋,通過實現(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 的動態(tài)數(shù)據(jù)。在下面的示例中了袁,PizzaDeliveryAttributes 描述了以下靜態(tài)數(shù)據(jù):訂購的比薩餅數(shù)量朗恳、客戶需要支付的金額以及訂單號。請注意代碼如何定義 Activity.ContentState 來封裝動態(tài)數(shù)據(jù):送披薩的司機的姓名和預(yù)計送達時間载绿。此外粥诫,該示例定義了類型別名 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
}

為您的實時活動創(chuàng)建配置

添加代碼以使用 ActivityAttributes 結(jié)構(gòu)來描述 Live Activity 中顯示的數(shù)據(jù)后崭庸,添加代碼以在小部件實現(xiàn)中返回 ActivityConfiguration怀浆。以下示例使用上一個示例中的 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)提供小部件怕享,請將 Live Activity 添加到您的 WidgetBundle执赡。如果您沒有 WidgetBundle(例如,如果您只提供一個小部件)函筋,請按照創(chuàng)建小部件擴展中的描述創(chuàng)建一個小部件包沙合,然后將 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)建鎖定屏幕視圖

要創(chuàng)建 Live Activity 的用戶界面跌帐,您可以在之前創(chuàng)建的小部件擴展中使用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 點脸狸,系統(tǒng)可能會截斷鎖定屏幕上的實時活動最仑。

創(chuàng)建緊湊和最小的視圖

實時活動出現(xiàn)在支持它的設(shè)備的靈動島中。當(dāng)您啟動一個 Live Activity 并且它是唯一一個活躍的 Live Activity 時肥惭,緊湊的前導(dǎo)視圖和尾隨視圖一起出現(xiàn)盯仪,以在 Dynamic Island 中形成一個有凝聚力的視圖。當(dāng)多個 Live Activity 處于活動狀態(tài)時(無論是來自您的應(yīng)用程序還是來自多個應(yīng)用程序)蜜葱,系統(tǒng)會選擇哪些 Live Activity 可見并使用每個最小視圖顯示兩個:一個最小視圖顯示為附加到靈動島,而另一個顯示為分離.

筆記
默認(rèn)情況下耀石,Dynamic Island 中的緊湊和最小視圖使用黑色背景顏色和白色文本牵囤。使用keylineTint(_:)修改器將可選的色調(diào)應(yī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)建擴展視圖

除了緊湊和最小視圖之外炕贵,您還必須支持?jǐn)U展視圖。當(dāng)一個人觸摸并持有一個緊湊或最小的視圖時野崇,它會出現(xiàn)称开,并且也會短暫出現(xiàn)以用于實時活動更新。當(dāng)您更新實時活動時乓梨,沒有靈動島的設(shè)備也會將擴展視圖顯示為橫幅鳖轰。使用DynamicIslandExpandedRegionPosition指定您希望 SwiftUI 將內(nèi)容放置在何處的詳細(xì)說明。以下示例顯示了披薩外賣應(yīng)用程序如何創(chuàng)建其擴展視圖:

@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)
        }
    }
}

筆記
如果靈動島的高度超過 160 點扶镀,系統(tǒng)可能會截斷靈動島中的實時活動蕴侣。

為了呈現(xiàn)展開的 Live Activity 中出現(xiàn)的視圖,系統(tǒng)將展開的視圖劃分為不同的區(qū)域臭觉。請注意該示例如何返回一個指定多個DynamicIslandExpandedRegion 對象的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)容的寬度场仲,同時考慮前導(dǎo)和尾隨內(nèi)容的最小寬度</u>。然后系統(tǒng)根據(jù)其垂直位置放置前導(dǎo)和尾隨內(nèi)容并確定其大小退疫。默認(rèn)情況下渠缕,前導(dǎo)視圖和尾隨視圖接收相同數(shù)量的水平空間。
    [圖片上傳失敗...(image-45ee62-1665454932342)]
    您可以通過將優(yōu)先級傳遞給init(_:priority:content:)初始化程序來告訴系統(tǒng)優(yōu)先考慮 DynamicIslandExpandedRegion 視圖之一褒繁。系統(tǒng)以動態(tài)島的全寬呈現(xiàn)具有最高優(yōu)先級的視圖亦鳞。

筆記
如果內(nèi)容太寬而無法出現(xiàn)在 TrueDepth 相機旁邊的前導(dǎo)位置,請使用belowIfTooWide修飾符來渲染 TrueDepth 相機下方的前導(dǎo)內(nèi)容棒坏。

使用自定義顏色

默認(rèn)情況下燕差,系統(tǒng)使用默認(rèn)的文本原色和最適合用戶鎖定屏幕的 Live Activity 的背景顏色。要設(shè)置自定義色調(diào)顏色坝冕,請使用視圖修飾符activityBackgroundTint(_:)徒探。此外,使用activitySystemActionForegroundColor(_:)視圖修飾符自定義允許人們在鎖定屏幕上結(jié)束實時活動的輔助按鈕的文本顏色喂窟。
要設(shè)置自定義背景色調(diào)顏色的半透明测暗,請使用opacity(_:)視圖修改器或指定不透明背景顏色央串。

筆記
在包括 Always-On Retina 顯示屏的設(shè)備上,系統(tǒng)會調(diào)暗屏幕以延長電池壽命碗啄,并在鎖定屏幕上呈現(xiàn)實時活動质和,就像在暗模式下一樣。使用 SwiftUI 的isLuminanceReduced環(huán)境值來檢測 Always On 并使用在 Always On 中看起來很棒的圖像稚字。

在您的應(yīng)用中創(chuàng)建深層鏈接

人們點擊實時活動來啟動您的應(yīng)用程序饲宿。為了改善用戶體驗,您可以使用widgetURL(_:)從鎖定屏幕胆描、緊湊的前導(dǎo)瘫想、緊湊的尾隨和最少的視圖創(chuàng)建到您的應(yīng)用程序的深層鏈接。當(dāng)緊湊的前導(dǎo)視圖和尾隨視圖可見時袄友,請確保它們都鏈接到應(yīng)用程序中的同一屏幕殿托。

擴展視圖提供了額外的選項來創(chuàng)建應(yīng)用程序的深層鏈接,以便使用 SwiftUI 的Link.例如剧蚣,披薩外賣應(yīng)用程序可能包含兩個 SwiftUI 視圖支竹。一個視圖可以在應(yīng)用程序中打開當(dāng)前送貨的地圖,第二個視圖可以打開一個屏幕鸠按,讓人們可以打電話給送披薩的人礼搁。

確保現(xiàn)場活動可用

現(xiàn)場活動僅在 iPhone 上可用目尖。如果您的應(yīng)用可在多個平臺上使用并提供小部件擴展馒吴,請確保實時活動在運行時可用。此外瑟曲,用戶可以在“設(shè)置”應(yīng)用中選擇停用應(yīng)用的實時活動饮戳。

要查看 Live Activity 是否可用以及用戶是否允許您的應(yīng)用使用 Live Activity:

  • 使用areActivitiesEnabled同步確定是否在您的應(yīng)用中顯示用戶界面以啟動 Live Activity。
  • 通過使用activityEnablementUpdates觀察流中的任何用戶授權(quán)更改來接收異步用戶授權(quán)更新并相應(yīng)地響應(yīng)它們洞拨。

筆記
一個應(yīng)用可以啟動多個 Live Activity扯罐,而一個設(shè)備可以從多個應(yīng)用運行 Live Activity。除了確保 Live Activity 可用之外烦衣,在開始歹河、更新或結(jié)束 Live Activity 時始終優(yōu)雅地處理任何錯誤。例如花吟,啟動 Live Activity 可能會失敗秸歧,因為用戶的設(shè)備可能已達到其活動 Live Activity 的限制。

開始現(xiàn)場活動

當(dāng)應(yīng)用程序在前臺時衅澈,您可以在應(yīng)用程序代碼中使用request(attributes:contentState:pushType:)函數(shù)啟動 Live Activity键菱。它將您創(chuàng)建的屬性和內(nèi)容狀態(tài)作為參數(shù)來提供顯示在 Live Activity 中的初始值,并告訴系統(tǒng)哪些數(shù)據(jù)是動態(tài)的矾麻。如果您實施遠(yuǎn)程推送通知來更新 Live Activity纱耻,還需要提供 pushType 參數(shù)芭梯。

以下代碼示例從前面的示例中為披薩外賣應(yīng)用啟動了一個新的 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).")
}

請注意上面的代碼片段如何不傳遞pushType參數(shù)并在不使用遠(yuǎn)程推送通知更新其內(nèi)容的情況下啟動 Live Activity险耀。它還將返回的 Live Activity 對象存儲在可用于更新和結(jié)束 Live Activity 的deliveryActivity屬性中弄喘。有關(guān)使用遠(yuǎn)程推送通知更新您的實時活動的更多信息,請參閱使用遠(yuǎn)程推送通知更新和結(jié)束您的實時活動甩牺。

筆記
您只能在應(yīng)用程序處于前臺時從應(yīng)用程序啟動實時活動蘑志。但是,您可以在應(yīng)用程序在后臺運行時更新或結(jié)束 Live Activity - 例如贬派,通過使用Background Tasks急但。

更新實時活動

當(dāng)您從應(yīng)用程序啟動 Live Activity 時,使用您在啟動 Live Activity 時收到的Activity對象的update(using:)函數(shù)更新顯示在 Live Activity 中的數(shù)據(jù)搞乏。要檢索應(yīng)用程序的活動實時活動波桩,請使用activities.

例如,披薩配送應(yīng)用程序可以更新顯示配送狀態(tài)的 Live Activity请敦,其中包含新的配送時間和新的司機镐躲。它還可以使用update(using:alertConfiguration:)函數(shù)在 iPhone 和 Apple Watch 上顯示警報,告知人們新的 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)將titlebody屬性用于alert匣椰。在 iPhone 上裆熙,系統(tǒng)不會顯示常規(guī)alert,而是顯示靈動島中展開的實時活動禽笑。在不支持靈動島的設(shè)備上入录,系統(tǒng)會在主屏幕上顯示一個橫幅,該橫幅使用您的實時活動的擴展視圖佳镜。

動畫內(nèi)容更新

當(dāng)您定義 Live Activity 的用戶界面時僚稿,系統(tǒng)會忽略任何動畫修改器,例如withAnimation(::),和animation(_:value:)邀杏,而是使用系統(tǒng)的動畫時間贫奠。但是,當(dāng) Live Activity 的動態(tài)內(nèi)容發(fā)生變化時望蜡,系統(tǒng)會執(zhí)行一些動畫唤崭。文本視圖通過模糊的內(nèi)容過渡動畫內(nèi)容變化,并且系統(tǒng)為圖像和 SF 符號動畫內(nèi)容過渡脖律。如果您根據(jù)內(nèi)容或狀態(tài)更改從用戶界面添加或刪除視圖谢肾,視圖會淡入淡出。使用以下視圖轉(zhuǎn)換來配置這些內(nèi)置轉(zhuǎn)換:opacity小泉、move(edge:)芦疏、slide冕杠、push(from:)或它們的組合。此外酸茴,使用numericText(countsDown:)請求計時器文本的動畫分预。

筆記
在包含 Always On Retina 顯示屏的設(shè)備上,系統(tǒng)不會執(zhí)行動畫以保持 Always On 的電池壽命薪捍。確保在動畫內(nèi)容更改之前使用 SwiftUI 的isLuminanceReduced環(huán)境值來檢測 Always On笼痹。

從您的應(yīng)用程序中結(jié)束實時活動

始終在關(guān)聯(lián)的任務(wù)或?qū)崟r事件結(jié)束后結(jié)束實時活動。已結(jié)束的實時活動將保留在鎖定屏幕上酪穿,直到用戶將其刪除或系統(tǒng)自動將其刪除凳干。自動刪除取決于您為函數(shù)end(using:dismissalPolicy:)提供的解雇策略。此外被济,始終包含更新的Activity.ContentState以確保實時活動在結(jié)束后顯示最新和最終的內(nèi)容更新救赐。這很重要,因為實時活動可以在鎖定屏幕上保持可見一段時間只磷。

以下示例顯示了披薩外賣應(yīng)用程序如何結(jié)束一個實時活動经磅,該活動顯示比薩送達時訂單的交付狀態(tài):

let finalDeliveryStatus = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "Anne Johnson", deliveryTimer: Date.now...Date())

Task {           
  await deliveryActivity?.end(using:finalDeliveryStatus, dismissalPolicy: .default)
}

上面的示例使用default解雇政策。因此喳瓣,實時活動結(jié)束后會在鎖定屏幕上顯示一段時間馋贤,以允許用戶瀏覽他們的手機以查看最新信息。用戶可以隨時選擇移除 Live Activity畏陕,或者系統(tǒng)在活動結(jié)束四小時后自動移除配乓。

要立即刪除從鎖定屏幕結(jié)束的實時活動,請使用immediate惠毁∮糖郏或者,用于after(_:)`指定四小時窗口內(nèi)的日期鞠绰。雖然您可以提供任何日期腰埂,但系統(tǒng)會在給定日期之后或在實時活動結(jié)束后四個小時后刪除已結(jié)束的實時活動 - 以先到者為準(zhǔn)。

用戶可以隨時從鎖定屏幕中刪除您的實時活動蜈膨。這會結(jié)束您的 Live Activity屿笼,但不會結(jié)束或取消用戶啟動 Live Activity 的操作。例如翁巍,用戶可以從鎖定屏幕中刪除他們的披薩外賣的實時活動驴一,但這不會取消披薩訂單。當(dāng)用戶或系統(tǒng)刪除實時活動時ActivityState更改為ActivityState.dismissed灶壶。

使用遠(yuǎn)程推送通知更新或結(jié)束您的實時活動

除了使用 ActivityKit 從您的應(yīng)用程序更新和結(jié)束實時活動之外肝断,您還可以使用從服務(wù)器發(fā)送到 Apple 推送通知服務(wù) (APN) 的遠(yuǎn)程推送通知更新或結(jié)束實時活動。要了解有關(guān)使用遠(yuǎn)程推送通知更新您的實時活動的更多信息,請參閱使用遠(yuǎn)程推送通知更新和結(jié)束您的實時活動胸懈。

跟蹤更新

當(dāng)您啟動 Live Activity 時担扑,ActivityKit 會返回一個Activity對象。除了唯一標(biāo)識每個活動的id之外趣钱,Activity還提供觀察內(nèi)容狀態(tài)涌献、活動狀態(tài)和推送令牌更新的序列。使用相應(yīng)的序列在您的應(yīng)用中接收更新羔挡,使您的應(yīng)用和 Live Activity 保持同步洁奈,并響應(yīng)更改的數(shù)據(jù):

  • 要觀察正在進行的 Live Activity 的狀態(tài)——例如间唉,確定它是處于活動狀態(tài)還是已經(jīng)結(jié)束——使用activityStateUpdates

  • 要觀察 Live Activity 動態(tài)內(nèi)容的變化绞灼,請使用contentState

  • 要觀察 Live Activity 的推送令牌的變化,請使用pushTokenUpdates

獲取活動列表

您的應(yīng)用可以啟動多個 Live Activity呈野。例如低矮,體育應(yīng)用程序可能允許用戶為他們感興趣的每個現(xiàn)場體育比賽啟動Live Activity。如果您的應(yīng)用程序啟動多個Live Activity被冒,請使用activityUpdates函數(shù)獲取有關(guān)您的應(yīng)用程序正在進行的Live Activity的通知军掂。跟蹤正在進行的 Live Activity 以確保您的應(yīng)用程序的數(shù)據(jù)與 ActivityKit 跟蹤的活動 Live Activity 同步。

以下代碼段顯示了披薩外賣應(yīng)用程序如何檢索正在進行的活動列表:

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

獲取所有活動的另一個用例是維護正在進行的實時活動昨悼,并確保您不會讓任何活動持續(xù)運行超過需要的時間蝗锥。例如,系統(tǒng)可能會停止您的應(yīng)用程序率触,或者您的應(yīng)用程序可能會在 Live Activity 處于活動狀態(tài)時崩潰终议。當(dāng)應(yīng)用下次啟動時,檢查是否有任何活動仍處于活動狀態(tài)葱蝗,更新應(yīng)用存儲的 Live Activity 數(shù)據(jù)穴张,并結(jié)束任何不再相關(guān)的 Live Activity。

也可以看看

現(xiàn)場活動實施

使用遠(yuǎn)程推送通知更新和結(jié)束您的實時活動
當(dāng)您開始實時活動時接收推送令牌两曼,并使用它通過遠(yuǎn)程推送通知更新或結(jié)束您的實時活動皂甘。
class Activity 用于啟動、更新和結(jié)束實時活動的對象悼凑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偿枕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子户辫,更是在濱河造成了極大的恐慌渐夸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寸莫,死亡現(xiàn)場離奇詭異捺萌,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門桃纯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酷誓,“玉大人,你說我怎么就攤上這事态坦⊙问” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵伞梯,是天一觀的道長玫氢。 經(jīng)常有香客問我,道長谜诫,這世上最難降的妖魔是什么漾峡? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮喻旷,結(jié)果婚禮上生逸,老公的妹妹穿的比我還像新娘。我一直安慰自己且预,他們只是感情好槽袄,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锋谐,像睡著了一般遍尺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涮拗,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天乾戏,我揣著相機與錄音,去河邊找鬼多搀。 笑死歧蕉,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的康铭。 我是一名探鬼主播惯退,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼从藤!你這毒婦竟也來了催跪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤夷野,失蹤者是張志新(化名)和其女友劉穎懊蒸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悯搔,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡骑丸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片通危。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡铸豁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出菊碟,到底是詐尸還是另有隱情节芥,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布逆害,位于F島的核電站头镊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏魄幕。R本人自食惡果不足惜相艇,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梅垄。 院中可真熱鬧厂捞,春花似錦、人聲如沸队丝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽机久。三九已至,卻和暖如春赔嚎,著一層夾襖步出監(jiān)牢的瞬間膘盖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工尤误, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留侠畔,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓损晤,卻偏偏與公主長得像软棺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尤勋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345