SwiftUI:关联Live Activity状态更新列表行的显示与操作
SwiftUI列表与Live Activity状态同步解决方案
核心思路
利用ActivityKit提供的系统API直接查询当前活跃的Live Activity实例,无需自行维护内存或本地存储,通过监听系统通知同步状态,实现列表行的动态UI更新。
具体实现步骤
1. 定义Live Activity属性结构
确保你的ActivityAttributes包含能匹配列表计时器的唯一标识(如timerId),用于后续状态匹配:
import ActivityKit struct TimerAttributes: ActivityAttributes { struct ContentState: Codable, Hashable { var remainingTime: TimeInterval // 计时器动态状态 } let timerId: UUID // 与列表计时器ID对应 let timerName: String }
2. 列表视图中监听Live Activity状态
在列表视图中维护当前活跃的Activity列表,通过系统通知实时更新:
import SwiftUI import ActivityKit struct TimerListView: View { let timers: [TimerModel] // 你的计时器数据源 @State private var activeActivities: [Activity<TimerAttributes>] = [] var body: some View { List(timers) { timer in HStack { Text(timer.name) Spacer() // 显示已跟踪标记 if isTracked(timerId: timer.id) { Image(systemName: "pin.fill") .foregroundColor(.orange) } } .swipeActions(edge: .leading) { if isTracked(timerId: timer.id) { Button("untrack") { endTracking(timerId: timer.id) } .tint(.red) } else { Button("track") { startTracking(timer: timer) } .tint(.green) } } } .task { // 初始化加载活跃Activity activeActivities = Activity<TimerAttributes>.activities // 监听Activity状态变化通知 NotificationCenter.default.addObserver( forName: Activity.activityDidChangeNotification, object: nil, queue: .main ) { _ in activeActivities = Activity<TimerAttributes>.activities } } } }
3. 实现状态判断与操作逻辑
添加辅助方法判断计时器是否被跟踪,以及启动/结束Live Activity的逻辑:
extension TimerListView { // 判断计时器是否处于跟踪状态 private func isTracked(timerId: UUID) -> Bool { activeActivities.contains { $0.attributes.timerId == timerId } } // 启动Live Activity private func startTracking(timer: TimerModel) { let attributes = TimerAttributes(timerId: timer.id, timerName: timer.name) let initialState = TimerAttributes.ContentState(remainingTime: timer.duration) do { try Activity<TimerAttributes>.request(attributes: attributes, contentState: initialState) } catch { print("启动跟踪失败: \(error.localizedDescription)") } } // 结束Live Activity private func endTracking(timerId: UUID) { guard let activity = activeActivities.first(where: { $0.attributes.timerId == timerId }) else { return } Task { await activity.end(dismissalPolicy: .immediate) // 立即更新列表状态 activeActivities.removeAll { $0.id == activity.id } } } } // 示例计时器数据模型 struct TimerModel: Identifiable { let id: UUID let name: String let duration: TimeInterval }
关键说明
- 无需手动维护引用:通过
Activity<TimerAttributes>.activities直接获取系统中所有活跃的同类型Live Activity,避免内存丢失问题。 - 实时状态同步:借助
Activity.activityDidChangeNotification监听系统通知,在Live Activity启动/结束时自动刷新列表。 - 精准匹配:通过计时器唯一ID与Activity属性中的
timerId关联,确保状态判断准确。
内容的提问来源于stack exchange,提问作者finiteloop
相关产品推荐
相关产品推荐

